如何在无唯一标识场景下将CC_TEMP数据无重复插入CC_PERM
CC_TEMP数据插入CC_PERM的去重实现方案
判断重复的核心依据是三个业务字段[Record Type]、[Segment Code]、[Headquarters Code]完全匹配,优先用稳定性最高的NOT EXISTS方案实现,不需要依赖CTE,也不会出现重复插入问题。
生产环境推荐写法(无额外依赖、兼容性强)
直接通过NOT EXISTS关联主表做存在性判断,过滤已存在数据后再插入:
INSERT INTO CC_PERM ( [Record Type], [Segment Code], [Headquarters Code] ) SELECT t.[Record Type], t.[Segment Code], t.[Headquarters Code] FROM CC_TEMP t WHERE NOT EXISTS ( SELECT 1 FROM CC_PERM p WHERE p.[Record Type] = t.[Record Type] AND p.[Segment Code] = t.[Segment Code] AND p.[Headquarters Code] = t.[Headquarters Code] );
- 如果CC_TEMP表内部本身存在三个业务字段完全一致的重复数据,只需要在SELECT子句加
DISTINCT关键字先对临时表去重即可,避免临时表内部的重复数据被写入主表:
-- CC_TEMP自身含重复数据时的写法 INSERT INTO CC_PERM ( [Record Type], [Segment Code], [Headquarters Code] ) SELECT DISTINCT t.[Record Type], t.[Segment Code], t.[Headquarters Code] FROM CC_TEMP t WHERE NOT EXISTS ( SELECT 1 FROM CC_PERM p WHERE p.[Record Type] = t.[Record Type] AND p.[Segment Code] = t.[Segment Code] AND p.[Headquarters Code] = t.[Headquarters Code] );
此前CTE方案失败的常见原因
- 未对CC_TEMP内部的重复数据做去重处理,CTE返回多条同业务键的数据,最终插入重复值
- 判重关联条件漏写业务字段,没有把三个字段全作为匹配条件,导致存在性判断逻辑错误
- 用
NOT IN做判重时,遇到字段存NULL值的场景会出现判断逻辑失效,漏过滤已存在数据
CTE方案的正确写法
如果业务场景必须用CTE实现,参考以下写法,先对临时表去重再通过左连判断主表是否存在对应记录:
;WITH TempUniqueData AS ( SELECT DISTINCT [Record Type], [Segment Code], [Headquarters Code] FROM CC_TEMP ) INSERT INTO CC_PERM ( [Record Type], [Segment Code], [Headquarters Code] ) SELECT tud.[Record Type], tud.[Segment Code], tud.[Headquarters Code] FROM TempUniqueData tud LEFT JOIN CC_PERM p ON tud.[Record Type] = p.[Record Type] AND tud.[Segment Code] = p.[Segment Code] AND tud.[Headquarters Code] = p.[Headquarters Code] WHERE p.recID IS NULL;
长期优化建议:给CC_PERM的三个业务字段创建联合唯一约束,从数据库层面直接拦截重复数据,不需要每次插入都手动写判重逻辑,从根源避免重复数据产生。
内容的提问来源于stack exchange,提问作者Bert Gregor
相关产品推荐
相关产品推荐

