避免在SQL Server中的INSERT INTO SELECT查询中重复

Ash*_*pta 97 sql t-sql sql-server sql-insert

我有以下两个表:

Table1
----------
ID   Name
1    A
2    B
3    C

Table2
----------
ID   Name
1    Z
Run Code Online (Sandbox Code Playgroud)

我需要从数据插入Table1Table2.我可以使用以下语法:

INSERT INTO Table2(Id, Name) SELECT Id, Name FROM Table1
Run Code Online (Sandbox Code Playgroud)

但是,在我的情况下,重复的ID可能存在Table2(在我的情况下,它只是" 1")并且我不想再次复制,因为这会引发错误.

我可以这样写:

IF NOT EXISTS(SELECT 1 FROM Table2 WHERE Id=1)
INSERT INTO Table2 (Id, name) SELECT Id, name FROM Table1 
ELSE
INSERT INTO Table2 (Id, name) SELECT Id, name FROM Table1 WHERE Table1.Id<>1
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法可以不使用IF - ELSE?我想避免INSERT INTO-SELECT基于某些条件的两个陈述.

OMG*_*ies 185

使用NOT EXISTS:

INSERT INTO TABLE_2
  (id, name)
SELECT t1.id,
       t1.name
  FROM TABLE_1 t1
 WHERE NOT EXISTS(SELECT id
                    FROM TABLE_2 t2
                   WHERE t2.id = t1.id)
Run Code Online (Sandbox Code Playgroud)

使用NOT IN:

INSERT INTO TABLE_2
  (id, name)
SELECT t1.id,
       t1.name
  FROM TABLE_1 t1
 WHERE t1.id NOT IN (SELECT id
                       FROM TABLE_2)
Run Code Online (Sandbox Code Playgroud)

使用LEFT JOIN/IS NULL:

INSERT INTO TABLE_2
  (id, name)
   SELECT t1.id,
          t1.name
     FROM TABLE_1 t1
LEFT JOIN TABLE_2 t2 ON t2.id = t1.id
    WHERE t2.id IS NULL
Run Code Online (Sandbox Code Playgroud)

在三个选项中,LEFT JOIN/IS NULL效率较低.有关详细信息,请参阅此链接.

  • `NOT EXISTS`对于复合主键特别有用,`NOT IN`则不起作用 (9认同)
  • 只是对NOT EXISTS版本的澄清,你需要一个WITH(HOLDLOCK)提示或者不会进行锁定(因为没有要锁定的行!)所以另一个线程可以在你下面插入行. (8认同)
  • 有意思,因为我一直认为加入比次选更快.也许这仅适用于直接连接,不适用于左连接. (2认同)

Dun*_*can 33

在MySQL中你可以这样做:

INSERT IGNORE INTO Table2(Id, Name) SELECT Id, Name FROM Table1
Run Code Online (Sandbox Code Playgroud)

SQL Server有类似的东西吗?

  • 不完全正确.创建唯一索引时,可以将其设置为"忽略重复",在这种情况下,SQL Server将忽略任何添加重复的尝试. (13认同)
  • +1教育我这个.非常好的语法.绝对比我使用的更短更好.不幸的是,Sql server没有这个. (5认同)
  • 而且SQL Server仍然无法...可悲。 (2认同)
  • 那么SQL Server还不能吗? (2认同)
  • 而且还是不能 (2认同)

小智 6

我刚遇到类似的问题,DISTINCT关键字有效:

INSERT INTO Table2(Id, Name) SELECT DISTINCT Id, Name FROM Table1
Run Code Online (Sandbox Code Playgroud)

  • 除非我完全误解你,否则如果你在插入_from_的集合中有重复项,这将有效.但是,如果您插入的集合可能是"insert into"表中已有的数据重复,则不会有帮助. (15认同)

小智 5

按照 IanC 的建议使用ignore Duplicates唯一索引是我针对类似问题的解决方案,使用 Option 创建索引WITH IGNORE_DUP_KEY

In backward compatible syntax
, WITH IGNORE_DUP_KEY is equivalent to WITH IGNORE_DUP_KEY = ON.
Run Code Online (Sandbox Code Playgroud)

参考:index_option


小智 5

我最近
遇到了同样的问题......这是在 MS SQL Server 2017 中对我有用的东西......
主键应该设置在表 2 中的 ID 上......
列和列属性当然应该是相同的表。这将在您第一次运行以下脚本时起作用。表1中的重复ID,不会插入...

如果你第二次运行它,你会得到一个

违反 PRIMARY KEY 约束错误

这是代码:

Insert into Table_2
Select distinct *
from Table_1
where table_1.ID >1
Run Code Online (Sandbox Code Playgroud)