SQLNice

首页/博客/MySQL vs PostgreSQL 格式化差异

MySQL vs PostgreSQL 格式化差异完全指南(2026)

2026-01-29
阅读时间: 8 分钟
数据库对比

MySQL 和 PostgreSQL 是世界上最流行的两大开源数据库系统,虽然它们都支持标准 SQL,但在具体的 SQL 语法、格式化规范和最佳实践上存在显著差异。本文深入对比两者在引号使用、标识符规范、函数语法、数据类型等方面的差异,帮助你在两个数据库之间平滑迁移和格式化代码。

无论你是从 MySQL 迁移到 PostgreSQL,还是需要维护多数据库系统,理解这些格式化差异都能避免常见错误,提升代码质量。

📊快速对比总览

特性MySQLPostgreSQL
标识符引号`反引号`"双引号"
字符串引号'单引号'"双引号"'单引号'
大小写敏感默认不敏感标识符加引号后敏感
字符串连接CONCAT()|| 运算符
LIMIT 语法LIMIT n OFFSET mLIMIT n OFFSET m
自增主键AUTO_INCREMENTSERIALGENERATED
布尔类型TINYINT(1)BOOLEAN
日期函数NOW()NOW()CURRENT_TIMESTAMP

1引号使用:最核心的差异

这是 MySQL 和 PostgreSQL 格式化中最容易出错的差异。理解引号规则是迁移代码的关键。

MySQL:反引号 ` 用于标识符

-- MySQL 示例
SELECT `user_id`, `user_name`, 'literal_string'
FROM `users`
WHERE `status` = "active"  -- 字符串可用双引号

PostgreSQL:双引号 " 用于标识符

-- PostgreSQL 示例
SELECT "user_id", "user_name", 'literal_string'
FROM "users"
WHERE "status" = 'active'  -- 字符串必须用单引号

MySQL 规则

  • • 标识符(表名、列名):\`反引号\`
  • • 字符串:'单引号'"双引号"
  • • 保留字必须用反引号:\`order\`, \`group\`

PostgreSQL 规则

  • • 标识符(表名、列名):"双引号"
  • • 字符串:'单引号'
  • • 保留字必须用双引号:"order", "group"

迁移陷阱

将 MySQL 代码迁移到 PostgreSQL 时,必须将 \` 替换为 ",并确保字符串只用单引号。否则会导致语法错误或数据类型错误。

2标识符大小写敏感性

MySQL 和 PostgreSQL 在标识符大小写处理上有显著不同,这会影响代码的可移植性。

MySQL:默认不区分大小写

-- MySQL:以下三个查询等效
SELECT * FROM Users;
SELECT * FROM users;
SELECT * FROM USERS;

-- 列名也不区分大小写
SELECT UserID, userid, USERID FROM users;  -- 都指向同一列

PostgreSQL:自动转小写,除非加引号

-- PostgreSQL:不加引号会自动转小写
SELECT * FROM Users;  -- 实际查询 users 表
SELECT * FROM users;  -- 查询 users 表

-- 加引号后大小写敏感
SELECT * FROM "Users";  -- 查询 Users 表(区分大小写)
SELECT * FROM "users";  -- 查询 users 表

-- 常见错误
CREATE TABLE UserData (...);  -- 实际创建 userdata 表
SELECT * FROM UserData;       -- 查询 userdata(成功)
SELECT * FROM "UserData";     -- 查询 UserData(失败!)

最佳实践

建议统一使用小写标识符,避免加引号。这样代码在两个数据库之间更易迁移。如果必须使用大写或混合大小写,确保在 PostgreSQL 中始终加引号。

3字符串连接函数

字符串连接是 SQL 中常见操作,但两个数据库的语法完全不同。

MySQL:CONCAT() 函数

SELECT CONCAT(first_name, ' ', last_name) AS full_name
FROM users;

-- MySQL 支持 CONCAT_WS(带分隔符)
SELECT CONCAT_WS('-', year, month, day) AS date_str
FROM dates;

PostgreSQL:|| 运算符

SELECT first_name || ' ' || last_name AS full_name
FROM users;

-- PostgreSQL 也支持 CONCAT()
SELECT CONCAT(first_name, ' ', last_name) AS full_name
FROM users;

兼容性建议

如果需要跨数据库兼容,使用 CONCAT() 函数,两个数据库都支持。但 PostgreSQL 社区更推荐 || 运算符,因为它是 SQL 标准。

4日期时间函数差异

日期时间处理是两个数据库差异较大的领域,迁移时需要特别注意。

获取当前时间

MySQL

SELECT NOW();
SELECT CURRENT_TIMESTAMP;
SELECT CURDATE();  -- 仅日期
SELECT CURTIME();  -- 仅时间

PostgreSQL

SELECT NOW();
SELECT CURRENT_TIMESTAMP;
SELECT CURRENT_DATE;  -- 仅日期
SELECT CURRENT_TIME;  -- 仅时间

日期运算

MySQL

-- 加减天数
SELECT DATE_ADD(NOW(), INTERVAL 7 DAY);
SELECT DATE_SUB(NOW(), INTERVAL 1 MONTH);

-- 日期差
SELECT DATEDIFF('2026-01-29', '2026-01-01');

-- 格式化
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s');

PostgreSQL

-- 加减天数
SELECT NOW() + INTERVAL '7 days';
SELECT NOW() - INTERVAL '1 month';

-- 日期差
SELECT '2026-01-29'::DATE - '2026-01-01'::DATE;

-- 格式化
SELECT TO_CHAR(NOW(), 'YYYY-MM-DD HH24:MI:SS');

迁移要点

  • • MySQL 的 DATE_ADD/DATE_SUB → PostgreSQL 的 + INTERVAL
  • • MySQL 的 DATE_FORMAT → PostgreSQL 的 TO_CHAR
  • • MySQL 的 DATEDIFF → PostgreSQL 的日期减法运算

5数据类型对照

两个数据库的数据类型体系有所不同,迁移表结构时需要对照转换。

用途MySQLPostgreSQL
自增主键INT AUTO_INCREMENTSERIALBIGSERIAL
布尔值TINYINT(1)BOOLEAN
短文本VARCHAR(n)VARCHAR(n)TEXT
长文本TEXT, MEDIUMTEXT, LONGTEXTTEXT
二进制数据BLOBBYTEA
日期时间DATETIME, TIMESTAMPTIMESTAMP, TIMESTAMPTZ
JSONJSONJSON, JSONB

建表语句对比

MySQL

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    is_active TINYINT(1) DEFAULT 1,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

PostgreSQL

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

6LIMIT 和分页语法

两个数据库的 LIMIT 语法基本一致,但细节上有差异。

基本 LIMIT

MySQL

-- 取前 10 条
SELECT * FROM users LIMIT 10;

-- 跳过 20 条,取 10 条
SELECT * FROM users LIMIT 10 OFFSET 20;

-- MySQL 简写语法(不推荐)
SELECT * FROM users LIMIT 20, 10;  -- offset, limit

PostgreSQL

-- 取前 10 条
SELECT * FROM users LIMIT 10;

-- 跳过 20 条,取 10 条
SELECT * FROM users LIMIT 10 OFFSET 20;

-- PostgreSQL 不支持 LIMIT offset, limit 语法

注意

MySQL 的 LIMIT offset, limit 简写语法在 PostgreSQL 中不被支持。迁移时需改为标准的 LIMIT n OFFSET m 格式。

7NULL 值处理函数

处理 NULL 值时,两个数据库提供了不同的函数。

MySQL

-- IFNULL:如果为 NULL 返回替代值
SELECT IFNULL(phone, 'N/A') AS phone
FROM users;

-- COALESCE:返回第一个非 NULL 值
SELECT COALESCE(phone, email, 'No contact') AS contact
FROM users;

-- NULLIF:两值相等返回 NULL
SELECT NULLIF(status, 'unknown') AS status
FROM orders;

PostgreSQL

-- PostgreSQL 不支持 IFNULL
-- 使用 COALESCE 代替
SELECT COALESCE(phone, 'N/A') AS phone
FROM users;

-- COALESCE:返回第一个非 NULL 值
SELECT COALESCE(phone, email, 'No contact') AS contact
FROM users;

-- NULLIF:两值相等返回 NULL
SELECT NULLIF(status, 'unknown') AS status
FROM orders;

兼容性建议

优先使用 COALESCE(),它是 SQL 标准函数,两个数据库都支持。避免使用 MySQL 特有的 IFNULL()

8注释语法差异

两个数据库都支持标准 SQL 注释,但有细微差异。

MySQL

-- 单行注释(标准)
# 单行注释(MySQL 特有)
/* 多行注释 */

SELECT
    id,  -- 用户 ID
    name # 用户名
FROM users /* 用户表 */;

PostgreSQL

-- 单行注释(标准)
/* 多行注释 */

SELECT
    id,  -- 用户 ID
    name -- 用户名
FROM users /* 用户表 */;

-- PostgreSQL 不支持 # 注释

建议:使用标准的 --/* */ 注释,避免使用 MySQL 特有的 #

🛠️跨数据库格式化工具

使用自动化工具可以减少格式化错误,提高迁移效率。

SQLNice

智能识别数据库类型,自动适配格式化规则

立即使用
  • 支持 MySQL 和 PostgreSQL 方言
  • 自动转换引号、函数、数据类型
  • 在线工具,无需安装

pgFormatter

PostgreSQL 专用格式化工具,支持命令行和在线版本

github.com/darold/pgFormatter

SQL Formatter

支持多种数据库方言的开源格式化库

github.com/sql-formatter-org/sql-formatter

迁移检查清单

从 MySQL 迁移到 PostgreSQL(或反向)时,使用此检查清单确保代码兼容性。

📚总结

MySQL 和 PostgreSQL 在 SQL 格式化上的差异主要体现在引号规则、标识符大小写、函数语法、数据类型等方面。理解这些差异是跨数据库开发和迁移的关键。

核心差异

  • 引号:MySQL 用反引号 \`\`,PostgreSQL 用双引号 ""
  • 大小写:MySQL 不敏感,PostgreSQL 自动转小写(除非加引号)
  • 函数:字符串连接、日期运算、NULL 处理函数不同
  • 类型:自增、布尔、文本等数据类型定义不同

最佳实践

  • • 使用自动化工具(如 SQLNice)减少人工错误
  • • 优先使用 SQL 标准语法,提高可移植性
  • • 建立团队规范,明确目标数据库的格式标准
  • • 迁移后必须进行完整测试,验证逻辑正确性

无论你使用哪个数据库,掌握格式化差异都能让你的代码更规范、更易维护。使用工具辅助,但理解原理更重要。

智能识别数据库类型,一键格式化

SQLNice 自动适配 MySQL 和 PostgreSQL 格式化规则

立即使用 SQLNice