PostgreSQL 15 不支持 MERGE 命令,执行必报语法错误;其标准替代方案是 INSERT ... ON CONFLICT DO UPDATE/NOTHING,需基于唯一约束或主键,且依赖 EXCLUDED 伪表实现原子操作。
PostgreSQL 15 不支持 MERGE 命令
直接说结论:你在 navicat 里执行 merge,一定会报错。postgresql 直到 16 版本(2023年10月发布)才原生支持 merge,而 pg 15(2022年10月发布)压根没有这个语法。你看到的任何 merge 报错,比如 syntax error at or near "merge",不是 navicat 的问题,是 postgresql 本身不认。
常见误判场景:
- 从 MySQL 或 SQL Server 迁移过来的脚本,直接粘贴
MERGE INTO ...到 Navicat 执行 - Navicat 的 AI 助手生成了
MERGE示例(它可能默认按最新版 PG 推荐),但你的服务端是 PG 15 - 文档或教程没注明版本,误以为 PG 全系支持
PG 15 中替代 MERGE 的实际写法是 INSERT ... ON CONFLICT
PG 15 的标准替代方案是 INSERT ... ON CONFLICT DO UPDATE/NOTHING。它能覆盖绝大多数 MERGE 场景,且性能通常更好——因为它是原子操作,无需先查再插/更。
例如,想实现“存在则更新 status,不存在则插入”:
INSERT INTO orders (id, user_id, status, amount) VALUES (123, 456, 'shipped', 99.99) ON CONFLICT (id) DO UPDATE SET status = EXCLUDED.status, amount = EXCLUDED.amount;
注意关键点:
-
ON CONFLICT后必须跟一个**唯一约束或主键列名**(如(id)),不能是普通索引 -
EXCLUDED是 PG 特有伪表,代表本次 INSERT 尝试插入的那行数据 - 若冲突列不是主键而是唯一索引,确保该索引未被禁用或失效
在 Navicat 里分析这条 INSERT ... ON CONFLICT 的真实性能
Navicat 的「可视化执行计划」按钮(⚡ 图标)能帮你确认是否走索引、是否触发了锁竞争或回滚开销。
重点看执行计划中是否出现:
-
Index Scan using→ 正常,说明快速定位冲突行 Seq Scan on→ 危险!说明没命中唯一约束,PG 只能全表扫来判断冲突,性能雪崩
LockRows出现在计划里 → 表示已加行锁,高并发下可能成瓶颈实操建议:
- 执行前先在 Navicat 查询窗口运行
\d+ orders,确认id列确实有UNIQUE或PKEY标记 - 如果冲突条件涉及多列(如
(user_id, order_date)),必须建联合唯一索引,单列索引无效 - 避免在
ON CONFLICT的DO UPDATE子句里调用函数(如NOW()多次),PG 会重复计算
Navicat Monitor 能监控但不能替代执行计划分析
如果你装了
Navicat Monitor,它可以在「慢查询」面板里捕获到执行时间超阈值的INSERT ... ON CONFLICT,但它给不出为什么慢——比如是没走索引,还是DO UPDATE里触发了复杂子查询。它只告诉你“这句慢”,不告诉你“哪部分拖慢”。真正要定位,还是得回到 Navicat for PostgreSQL 的查询编辑器里,点「解释」或「解释并执行」,盯着
actual time和节点类型看。尤其注意loops值:如果loops=1000但actual time单次才 0.1ms,说明是批量语句里某一行触发了异常路径,而不是整条语句固有慢。











