八月 10, 2026 作者 Sqlinfy

MySQL 到 PostgreSQL 迁移:7 个重要的 SQL 差异

从 MySQL 迁移到 PostgreSQL 不只是更改几个函数名称。以下 7 个实用的 SQL 差异可能会影响架构、查询和应用程序行为。

正在准备文章 正在整理标题、代码示例和列表…

MySQL 和 PostgreSQL 都使用 SQL,但它们的解释方式并不总是相同。


一个查询在 MySQL 中看起来完全正常,迁移到 PostgreSQL 后却可能失败,或表现出不同的行为。


以下是迁移期间值得检查的 7 个差异。


1. 标识符引号


MySQL 通常使用反引号包围表名和列名:


SELECT `name`, `order`

FROM `customers`;


PostgreSQL 使用双引号表示带引号的标识符:


SELECT "name", "order"

FROM "customers";


当标识符包含空格、大写字母或保留字时,使用引号尤其重要。


更好的长期做法是尽可能使用不需要引号的简单小写标识符。


2. 自动生成的 ID


MySQL 表可能使用 AUTO_INCREMENT:


CREATE TABLE customers (

  id INT AUTO_INCREMENT PRIMARY KEY,

  name VARCHAR(100)

);


现代 PostgreSQL 的等效方式可以使用 identity 列:


CREATE TABLE customers (

  id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,

  name VARCHAR(100)

);


PostgreSQL 也支持 SERIAL,但对于新架构,identity 列提供了更清晰、基于标准的行为。


迁移数据后,请验证 PostgreSQL 序列是否会从导入的最高 ID 之后继续生成。


3. 布尔值


MySQL 应用程序经常使用 TINYINT 表示布尔值:


CREATE TABLE users (

  is_active TINYINT(1)

);


PostgreSQL 具有专用的 BOOLEAN 类型:


CREATE TABLE users (

  is_active BOOLEAN

);


诸如 1 和 0 这样的值可能需要转换为 TRUE 和 FALSE。


这一差异也可能影响应用程序代码、筛选条件、默认值和导入的数据。


4. 处理 NULL 值


MySQL 提供 IFNULL:


SELECT IFNULL(phone_number, 'Not provided')

FROM customers;


PostgreSQL 通常使用 COALESCE:


SELECT COALESCE(phone_number, 'Not provided')

FROM customers;


两个数据库都支持 COALESCE,使用它可以让未来的迁移更加容易。


不过,仍应仔细测试 NULL 在比较、连接、计算和条件表达式中的行为。


5. 日期运算


MySQL 可以使用 DATE_ADD 增加 7 天:


SELECT DATE_ADD(order_date, INTERVAL 7 DAY)

FROM orders;


PostgreSQL 可以使用 interval 表达相同的操作:


SELECT order_date + INTERVAL '7 days'

FROM orders;


可见的语法只是差异的一部分。


如果应用程序对此有要求,还应检查日期类型、时间戳、时区、月份边界和夏令时行为。


6. 拼接字符串


MySQL 通常使用 CONCAT:


SELECT CONCAT(first_name, ' ', last_name)

FROM customers;


PostgreSQL 支持 CONCAT,但也通常使用双竖线运算符:


SELECT first_name || ' ' || last_name

FROM customers;


当值可能为 NULL 时请务必小心。根据输入值的不同,不同的字符串连接方式可能会产生不同的结果。


请测试姓名、地址、报表标签以及其他组合多个列的表达式。


7. Upsert 语法


MySQL 可以使用 ON DUPLICATE KEY UPDATE 插入或更新一行:


INSERT INTO products (id, name, price)

VALUES (10, 'Keyboard', 49.99)

ON DUPLICATE KEY UPDATE

  name = VALUES(name),

  price = VALUES(price);


PostgreSQL 使用 ON CONFLICT:


INSERT INTO products (id, name, price)

VALUES (10, 'Keyboard', 49.99)

ON CONFLICT (id) DO UPDATE SET

  name = EXCLUDED.name,

  price = EXCLUDED.price;


PostgreSQL 语句会明确指定冲突目标。


转换 upsert 之前,请检查唯一约束和索引,因为它们决定了 PostgreSQL 可以检测到哪些冲突。


还应测试什么?


语法转换只是第一步。


转换 MySQL 查询或架构后,请使用具有代表性的数据比较源端和目标端的行为。


请检查:


• 行数

• NULL 值

• 自动生成的 ID

• 日期和时间结果

• 小数精度

• 大小写敏感性

• 排序顺序

• 重复数据处理

• 默认值


能够成功运行的 SQL,并不自动意味着其行为正确。


可靠的迁移工作流


实用的 MySQL 到 PostgreSQL 工作流如下:


理解源 SQL

将其转换为 PostgreSQL

检查特定方言的更改

查看诊断信息

使用具有代表性的数据进行测试

比较结果

验证完成后再部署


Sqlinfy 可以帮助在 MySQL 和 PostgreSQL 之间创建结构化的初步转换。不过,在生产环境中使用转换后的 SQL 之前,开发人员仍应进行审查和测试。


用你的 SQL 试试

把所学内容变成可检查的转换结果。

阅读 Sqlinfy 产品更新、SQL 转换技巧和数据库迁移实践。

继续阅读

最新文章

阅读更多近期文章。