MySQL vs PostgreSQL 格式化差异完全指南(2026)
MySQL 和 PostgreSQL 是世界上最流行的两大开源数据库系统,虽然它们都支持标准 SQL,但在具体的 SQL 语法、格式化规范和最佳实践上存在显著差异。本文深入对比两者在引号使用、标识符规范、函数语法、数据类型等方面的差异,帮助你在两个数据库之间平滑迁移和格式化代码。
无论你是从 MySQL 迁移到 PostgreSQL,还是需要维护多数据库系统,理解这些格式化差异都能避免常见错误,提升代码质量。
📊快速对比总览
| 特性 | MySQL | PostgreSQL |
|---|---|---|
| 标识符引号 | `反引号` | "双引号" |
| 字符串引号 | '单引号' 或 "双引号" | '单引号' 仅 |
| 大小写敏感 | 默认不敏感 | 标识符加引号后敏感 |
| 字符串连接 | CONCAT() | || 运算符 |
| LIMIT 语法 | LIMIT n OFFSET m | LIMIT n OFFSET m |
| 自增主键 | AUTO_INCREMENT | SERIAL 或 GENERATED |
| 布尔类型 | 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数据类型对照
两个数据库的数据类型体系有所不同,迁移表结构时需要对照转换。
| 用途 | MySQL | PostgreSQL |
|---|---|---|
| 自增主键 | INT AUTO_INCREMENT | SERIAL 或 BIGSERIAL |
| 布尔值 | TINYINT(1) | BOOLEAN |
| 短文本 | VARCHAR(n) | VARCHAR(n) 或 TEXT |
| 长文本 | TEXT, MEDIUMTEXT, LONGTEXT | TEXT |
| 二进制数据 | BLOB | BYTEA |
| 日期时间 | DATETIME, TIMESTAMP | TIMESTAMP, TIMESTAMPTZ |
| JSON | JSON | JSON, 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, limitPostgreSQL
-- 取前 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 方言
- 自动转换引号、函数、数据类型
- 在线工具,无需安装
✓迁移检查清单
从 MySQL 迁移到 PostgreSQL(或反向)时,使用此检查清单确保代码兼容性。
📚总结
MySQL 和 PostgreSQL 在 SQL 格式化上的差异主要体现在引号规则、标识符大小写、函数语法、数据类型等方面。理解这些差异是跨数据库开发和迁移的关键。
核心差异
- • 引号:MySQL 用反引号
\`\`,PostgreSQL 用双引号"" - • 大小写:MySQL 不敏感,PostgreSQL 自动转小写(除非加引号)
- • 函数:字符串连接、日期运算、NULL 处理函数不同
- • 类型:自增、布尔、文本等数据类型定义不同
最佳实践
- • 使用自动化工具(如 SQLNice)减少人工错误
- • 优先使用 SQL 标准语法,提高可移植性
- • 建立团队规范,明确目标数据库的格式标准
- • 迁移后必须进行完整测试,验证逻辑正确性
无论你使用哪个数据库,掌握格式化差异都能让你的代码更规范、更易维护。使用工具辅助,但理解原理更重要。
智能识别数据库类型,一键格式化
SQLNice 自动适配 MySQL 和 PostgreSQL 格式化规则
立即使用 SQLNice