为何每次执行MERGE语句都会向目标表插入全部数据?
问题分析与解决
核心问题1:Id取反导致匹配永远失败
你的源查询里把Id做了Id * (-1)的处理,这会让源表的Id变成负数,而目标表的Id应该是正常的正数,所以ON source.Id = target.Id这个匹配条件永远不成立,每次执行MERGE时所有源记录都被判定为“目标表中不存在”,自然会全量插入。
核心问题2:缺少修改记录的同步逻辑
当前MERGE只处理了“目标不存在则插入”的场景,没有处理“目标存在但源记录已修改”的更新逻辑,所以即使解决了匹配问题,修改过的记录也同步不了。
额外优化:简化CountryId的查询逻辑
原查询里重复查询了两次源库的Country表,效率很低,可以用JOIN来简化,同时避免嵌套子查询的冗余。
修正后的MERGE语句
MERGE INTO dbo.CountrySourceType AS target USING ( SELECT cst.Id, cst.Name, c.Id AS CountryId FROM [192.xxx.x.xxx].WebPortal.dbo.CountrySourceType cst JOIN [192.xxx.x.xxx].WebPortal.dbo.Country cs ON cs.Id = cst.CountryId JOIN dbo.Country c ON ISNULL(c.Name, '') = ISNULL(cs.Name, '') AND ISNULL(c.ContinentName, '') = ISNULL(cs.ContinentName, '') ) AS source ON source.Id = target.Id WHEN NOT MATCHED BY target THEN INSERT ([Name], [CountryId]) VALUES (source.Name, source.CountryId) WHEN MATCHED THEN UPDATE SET target.Name = source.Name, target.CountryId = source.CountryId;
修改说明
- 去掉了
Id * (-1)的错误处理,直接使用源表的原始Id,保证匹配条件能正常生效。 - 新增
WHEN MATCHED THEN UPDATE分支,当Id匹配时更新目标表的Name和CountryId字段,同步修改记录。 - 用JOIN替代嵌套子查询获取CountryId,既简化了代码,又提升了查询效率。
- 删除了原查询中冗余的
WHERE CountryId = cst.CountryId条件(这个条件等价于恒成立,没有过滤作用)。
内容的提问来源于stack exchange,提问作者tester
相关产品推荐
相关产品推荐

