SQL Server 2019两表同步:存在则更新金额、不存在则插入记录
SQL Server 2019 增量同步(存在更新/不存在插入)实现
前置说明
- 当前环境为SQL Server 2019 Express Edition,原生支持本次需求用到的所有语法
- 以下方案默认以
[Account ID]+[Time]作为业务唯一键(即同一账户同一时间点仅对应一条有效记录),你可以根据实际业务规则调整匹配字段 - 所有写操作默认包裹在事务中,避免误操作污染历史数据
推荐方案:使用MERGE语句单次实现
MERGE是SQL Server专门为"存在则更新、不存在则插入"的upsert场景设计的语法,单次执行即可完成逻辑,比拆分多语句的执行效率更高,也能规避并发场景下的重复键冲突。
BEGIN TRANSACTION; MERGE Table2 AS target USING Table1 AS source -- 配置记录匹配规则 ON target.[Account ID] = source.[Account ID] AND target.[Time] = source.[Time] -- 匹配到记录且金额发生变动时,更新对应字段 WHEN MATCHED AND target.Amount != source.Amount THEN UPDATE SET target.[Account Description] = source.[Account Description], target.Amount = source.Amount -- 目标表无匹配记录时,插入新行 WHEN NOT MATCHED BY TARGET THEN INSERT ( [Account ID], [Account Description], Amount, [Time] ) VALUES ( source.[Account ID], source.[Account Description], source.Amount, source.[Time] ); -- 执行完上述语句后,先查看消息栏返回的影响行数,和预期一致再执行COMMIT提交,异常则执行ROLLBACK回滚 -- COMMIT -- ROLLBACK
备选方案:拆分UPDATE+INSERT语句实现
如果不习惯使用MERGE语法,也可以拆分为更新、插入两步执行,逻辑完全一致:
BEGIN TRANSACTION; -- 第一步:更新已存在且金额有变动的记录 UPDATE target SET target.[Account Description] = source.[Account Description], target.Amount = source.Amount FROM Table2 target INNER JOIN Table1 source ON target.[Account ID] = source.[Account ID] AND target.[Time] = source.[Time] WHERE target.Amount != source.Amount; -- 第二步:插入目标表中不存在的新记录 INSERT INTO Table2 ( [Account ID], [Account Description], Amount, [Time] ) SELECT source.[Account ID], source.[Account Description], source.Amount, source.[Time] FROM Table1 source LEFT JOIN Table2 target ON target.[Account ID] = source.[Account ID] AND target.[Time] = source.[Time] WHERE target.[Account ID] IS NULL; -- 验证后执行提交/回滚 -- COMMIT -- ROLLBACK
注意事项
- 字段名包含空格时(比如
Account ID、Account Description),必须用方括号[]包裹,否则会触发语法错误 - 不要省略
Amount变动的判断条件,否则即使金额没有变化也会执行更新,产生不必要的事务日志,拖慢执行效率 - 正式执行前务必先在测试环境验证逻辑,生产环境执行时先不要提交事务,核对影响行数符合预期后再提交
内容的提问来源于stack exchange,提问作者SamBoo11
相关产品推荐
相关产品推荐

