所有内容均为测试可用,真实
当前位置:绿茶加糖-郭保升 > 数据库资料 > 正文

SQL 如何实现“存在则更新,不存在则新增”?

在数据库操作中,“存在则更新,不存在则新增”(即 UPSERT)是一个高频需求。例如:

  • 用户登录时自动更新最后登录时间。
  • 电商平台同步库存数据。
  • 接入第三方 API 时避免重复数据。
MYSQL

使用 "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);

子句说明

子句
作用
INSERT INTO
插入数据的标准语句。
ON DUPLICATE KEY UPDATE
当主键或唯一索引冲突时,触发更新操作。
VALUES(字段)
引用插入的值,用于更新字段。

注意事项

  • 必须设置唯一索引:需在表中定义主键或唯一索引。
  • 字段类型匹配:更新字段的数据类型必须与原字段一致。

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;

子句说明

子句
作用
ON CONFLICT (字段)
指定冲突字段(如 id 或 email)。
EXCLUDED.字段
引用插入的冲突行数据。
DO UPDATE SET
指定更新的字段和值。

注意事项

  • 必须设置唯一索引:需在表中定义主键或唯一索引。
  • 字段引用:使用 EXCLUDED 关键字引用插入的值。

SQL Server

使用 "MERGE INTO",适用于 SQL Server,语法复杂但功能强大。

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
MERGE INTO 目标表 AS targetUSING (源数据) AS sourceON (匹配条件)WHEN MATCHED THEN    UPDATE SET ...WHEN NOT MATCHED THEN    INSERT (...);    

子句说明

子句
作用
MERGE INTO
指定目标表
USING
提供源数据(可以是子查询或值列表)。
ON
定义匹配条件
WHEN MATCHED
匹配到记录时执行更新操作。
WHEN NOT MATCHED
未匹配到记录时执行插入操作。

注意事项

  • 源数据格式: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.字段);

子句说明

子句
作用
MERGE INTO
指定目标表
USING
提供源数据(可以是子查询或dual表)。
ON
定义匹配条件
WHEN MATCHED
匹配到记录时执行更新操作。
WHEN NOT MATCHED
未匹配到记录时执行插入操作。

注意事项

  • dual 表:Oracle 中单值插入需使用 FROM dual
  • 字段别名:USING 子句中的字段需定义别名。
  • 多行支持:可通过子查询插入多行数据。
 

案例:库存同步

需求:同步商品库存:

  • 如果商品已存在,更新库存数量。
  • 如果商品不存在,插入新商品。

MySQL 实现

  •  
  •  
  •  
  •  
  •  
INSERT INTO products (product_id, stock)VALUES (100150),       (1002100)ON DUPLICATE KEY UPDATE    stock = VALUES(stock);

PostgreSQL 实现

  •  
  •  
  •  
  •  
  •  
INSERT INTO products (product_id, stock)VALUES (100150),       (1002100)ON CONFLICT (product_id) DO UPDATE SET    stock = EXCLUDED.stock;

SQL Server 实现

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
MERGE INTO products AS targetUSING (VALUES (100150),(1002100)) 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);
总结
数据库
优点
缺点
MYSQL
语法简单,性能高
仅限 MySQL
PostgreSQL
支持复杂冲突处理
语法稍复杂
SQL Server
功能强大,适合复杂业务逻辑
语法冗长
Oracle
与 SQL Server 类似
需使用 dual 表
 

版权保护: 本文由 绿茶加糖-郭保升 原创,转载请保留链接: https://www.guobaosheng.com/shujuku/392.html