MERGE语句WHEN MATCHED子句插入报错的替代方案咨询
替代MERGE的stats数据同步方案
方案1:INSERT + NOT EXISTS(最简洁高效)
直接通过INSERT...SELECT结合NOT EXISTS子查询,精准插入statsHistory中不存在对应Id且DateGenerated为当日的记录,完全匹配你的需求:
CREATE PROCEDURE SyncStatsToHistory AS BEGIN SET NOCOUNT ON; DECLARE @Today DATE = CAST(GETDATE() AS DATE); -- 插入今日未缓存的stats记录 INSERT INTO statsHistory (Id, stat1, stat2, stat3, LastChangeDate, DateGenerated) SELECT s.Id, s.stat1, s.stat2, s.stat3, s.LastChangeDate, @Today FROM stats s WHERE NOT EXISTS ( SELECT 1 FROM statsHistory sh WHERE sh.Id = s.Id AND sh.DateGenerated = @Today ); END GO
逻辑说明
- 先获取当日日期
@Today,确保所有插入记录的DateGenerated统一为当天 NOT EXISTS子查询会检查:stats中的每条记录,在statsHistory里是否已有相同Id且DateGenerated为今日的条目- 仅当不存在时插入新行,完美实现「已有对应Id但日期不匹配时插入新行」的需求
方案2:CTE筛选后批量插入(可读性优先)
通过公共表表达式(CTE)先筛选出所有待插入的记录,再批量插入,逻辑清晰易扩展:
CREATE PROCEDURE SyncStatsToHistory AS BEGIN SET NOCOUNT ON; DECLARE @Today DATE = CAST(GETDATE() AS DATE); -- 用CTE找出今日未缓存的记录 WITH MissingHistoryRecords AS ( SELECT s.Id, s.stat1, s.stat2, s.stat3, s.LastChangeDate, @Today AS DateGenerated FROM stats s LEFT JOIN statsHistory sh ON s.Id = sh.Id AND sh.DateGenerated = @Today WHERE sh.Id IS NULL ) -- 批量插入筛选结果 INSERT INTO statsHistory (Id, stat1, stat2, stat3, LastChangeDate, DateGenerated) SELECT Id, stat1, stat2, stat3, LastChangeDate, DateGenerated FROM MissingHistoryRecords; END GO
性能优化建议
- 优先选用方案1,
NOT EXISTS在SQL Server中优化效率极高,适合大规模数据同步 - 给statsHistory表的
Id和DateGenerated字段建立联合索引:
该索引可大幅提升判断记录是否存在的查询速度CREATE NONCLUSTERED INDEX IX_statsHistory_Id_DateGenerated ON statsHistory (Id, DateGenerated);
内容的提问来源于stack exchange,提问作者M Leipper
相关产品推荐
相关产品推荐

