SQL Server插入多行数据时如何校验记录存在性避免重复插入
带重复校验的批量插入SQL实现
你原来单条插入的SELECT + NOT EXISTS逻辑完全可以直接复用在批量场景,只需要把单条待插入数据的子查询替换为多行数据集即可,有两种常用写法:
写法1:UNION ALL拼接多行数据(兼容所有SQL Server版本)
和你原有单条写法逻辑完全一致,没有版本兼容问题,只需要把多条待插入数据用UNION ALL连接成一个结果集即可:
INSERT INTO dbo.[User] (UserID, UserName) SELECT LIST.ID, LIST.STATUS_NAME FROM ( SELECT 104 AS ID, 'Ross' AS STATUS_NAME UNION ALL SELECT 105 AS ID, 'Colin' AS STATUS_NAME UNION ALL SELECT 106 AS ID, 'Town' AS STATUS_NAME UNION ALL SELECT 107 AS ID, 'Hayley' AS STATUS_NAME ) LIST WHERE NOT EXISTS ( SELECT 1 FROM dbo.[User] US WHERE US.UserID = LIST.ID AND US.UserName = LIST.STATUS_NAME ) GO
写法2:VALUES构造多行集合(SQL Server 2008及以上版本支持)
写法更简洁,不需要写多次SELECT,直接用VALUES一次性声明所有待插入行,再给列起别名即可,是目前更常用的写法:
INSERT INTO dbo.[User] (UserID, UserName) SELECT LIST.ID, LIST.STATUS_NAME FROM (VALUES (104, 'Ross'), (105, 'Colin'), (106, 'Town'), (107, 'Hayley') ) AS LIST(ID, STATUS_NAME) WHERE NOT EXISTS ( SELECT 1 FROM dbo.[User] US WHERE US.UserID = LIST.ID AND US.UserName = LIST.STATUS_NAME ) GO
注意事项
- 不要直接在原生
INSERT ... VALUES (),()语法外层加存在性判断,这种写法无法针对单条数据做校验,会出现要么所有行全插入、要么全不插入的问题,达不到跳过重复行的效果 User是SQL Server系统保留关键字,书写时建议加上方括号[User],避免SQL解析报错- 上述写法的校验逻辑和你原来的单条插入完全一致:仅当待插入行的
UserID和UserName同时和表现有记录匹配时,才会跳过该行,不会出现误跳过的情况 - 如果后续需要实现“存在则更新、不存在则插入”的逻辑,可以替换为
MERGE语法,仅做跳过重复插入的场景下,上述两种写法性能比MERGE更好。
内容的提问来源于stack exchange,提问作者DevOpS_PRO
相关产品推荐
相关产品推荐

