在数据库操作中,“存在则更新,不存在则新增”(即 UPSERT)是一个高频需求。例如:
使用 "ON DUPLICATE KEY UPDATE" 语法,适用于 MySQL 数据库,依赖 唯一索引 或 主键。
语法结构
INSERT INTO 表名 (字段1, 字段2, ...)VALUES (值1, 值2, ...)ON DUPLICATE KEY UPDATE 字段1 = VALUES(字段1), 字段2 = VALUES(字段2);
INSERT INTO 表名 (字段1, 字段2, ...)VALUES (值1, 值2, ...), (值1, 值2, ...), (值1, 值2, ...)ON DUPLICATE KEY UPDATE 字段1 = VALUES(字段1), 字段2 = VALUES(字段2);
子句说明
注意事项
-
字段类型匹配:更新字段的数据类型必须与原字段一致。
PostgreSQL
使用 "ON CONFLICT" 语法,适用于 PostgreSQL,支持多行插入和复杂冲突处理。
语法结构
INSERT INTO 表名 (字段1, 字段2, ...)VALUES (值1, 值2, ...)ON CONFLICT (冲突字段) DO UPDATE SET 字段1 = EXCLUDED.字段1, 字段2 = EXCLUDED.字段2;
INSERT INTO 表名 (字段1, 字段2, ...)VALUES (值1, 值2, ...), (值1, 值2, ...), (值1, 值2, ...)ON CONFLICT (冲突字段) DO UPDATE SET 字段1 = EXCLUDED.字段1, 字段2 = EXCLUDED.字段2;
子句说明
注意事项
-
必须设置唯一索引:需在表中定义主键或唯一索引。
-
字段引用:使用 EXCLUDED 关键字引用插入的值。
SQL Server
使用 "MERGE INTO",适用于 SQL Server,语法复杂但功能强大。
MERGE INTO 目标表 AS targetUSING (源数据) AS sourceON (匹配条件)WHEN MATCHED THEN UPDATE SET ...WHEN NOT MATCHED THEN INSERT (...);
子句说明
注意事项
-
源数据格式:USING 子句中的数据格式需与目标表匹配。
-
匹配条件:ON 子句需明确指定关联逻辑。
-
多行支持:可通过子查询插入多行数据。
Oracle
使用 "MERGE INTO", 与 SQL Server 类似,但语法略有不同。
MERGE INTO 目标表 uUSING (源数据) sON (匹配条件)WHEN MATCHED THEN UPDATE SET u.字段 = s.字段WHEN NOT MATCHED THEN INSERT (字段) VALUES (s.字段);
子句说明
注意事项
-
dual 表:Oracle 中单值插入需使用 FROM dual
-
字段别名:USING 子句中的字段需定义别名。
-
多行支持:可通过子查询插入多行数据。
案例:库存同步
需求:同步商品库存:
MySQL 实现
INSERT INTO products (product_id, stock)VALUES (1001, 50), (1002, 100)ON DUPLICATE KEY UPDATE stock = VALUES(stock);
PostgreSQL 实现
INSERT INTO products (product_id, stock)VALUES (1001, 50), (1002, 100)ON CONFLICT (product_id) DO UPDATE SET stock = EXCLUDED.stock;
SQL Server 实现
MERGE INTO products AS targetUSING (VALUES (1001, 50),(1002, 100)) AS source (product_id, stock)ON target.product_id = source.product_idWHEN MATCHED THEN UPDATE SET stock = source.stockWHEN NOT MATCHED THEN INSERT (product_id, stock) VALUES (source.product_id, source.stock);
Oracle 实现
MERGE INTO products pUSING (SELECT 1001 AS product_id, 50 AS stock FROM dual) sON (p.product_id = s.product_id)WHEN MATCHED THEN UPDATE SET p.stock = s.stockWHEN NOT MATCHED THEN INSERT (product_id, stock) VALUES (s.product_id, s.stock);