我有以下两个表:
Table1
----------
ID Name
1 A
2 B
3 C
Table2
----------
ID Name
1 Z
我需要将Table1
的数据插入Table2
。我可以使用以下语法:
INSERT INTO Table2(Id, Name) SELECT Id, Name FROM Table1
但是,在我的情况下,Table2
中可能存在重复的ID(在我的情况下,它只是“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
有没有更好的方法可以在不使用IF - ELSE
的情况下执行此操作?我想根据某些条件避免两个INSERT INTO-SELECT
语句。
答案 0 :(得分:178)
使用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)
使用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)
使用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
在这三个选项中,LEFT JOIN/IS NULL
效率较低。请参阅this link for more details。
答案 1 :(得分:30)
在MySQL中你可以这样做:
INSERT IGNORE INTO Table2(Id, Name) SELECT Id, Name FROM Table1
SQL Server有类似的东西吗?
答案 2 :(得分:6)
我遇到了类似的问题,DISTINCT关键字有效:
INSERT INTO Table2(Id, Name) SELECT DISTINCT Id, Name FROM Table1
答案 3 :(得分:3)
在唯一索引as suggested by IanC here上使用ignore Duplicates
是针对类似问题的解决方案,使用选项WITH IGNORE_DUP_KEY
创建索引
In backward compatible syntax
, WITH IGNORE_DUP_KEY is equivalent to WITH IGNORE_DUP_KEY = ON.
参考:index_option
答案 4 :(得分:3)
答案 5 :(得分:2)
我最近也遇到了同样的问题...
以下是在MS SQL Server 2017中对我有用的内容...
主键应在表2中的ID上设置...
当然,两个表之间的列和列属性应该相同。这将在您第一次运行以下脚本时起作用。表1中重复的ID将不会插入...
如果第二次运行它,您将获得
违反主键约束错误
这是代码:
Insert into Table_2
Select distinct *
from Table_1
where table_1.ID >1
答案 6 :(得分:0)
有点偏离主题,但是如果要将数据迁移到新表,并且可能的重复项位于原始表中,并且可能重复的列不是id,则为{ {1}}会:
GROUP BY
答案 7 :(得分:0)
在DELETE
之前的简单INSERT
就足够了:
DELETE FROM Table2 WHERE Id = (SELECT Id FROM Table1)
INSERT INTO Table2 (Id, name) SELECT Id, name FROM Table1
根据要保留的表的Table1
和Table2
配对,将Id
切换为name
。
答案 8 :(得分:0)
就我而言,我在源表中有重复的ID,因此这些建议均无效。我不在乎性能,只做过一次。 为了解决这个问题,我用光标一一记录下来,以忽略重复项。
所以这是代码示例:
DECLARE @c1 AS VARCHAR(12);
DECLARE @c2 AS VARCHAR(250);
DECLARE @c3 AS VARCHAR(250);
DECLARE MY_cursor CURSOR STATIC FOR
Select
c1,
c2,
c3
from T2
where ....;
OPEN MY_cursor
FETCH NEXT FROM MY_cursor INTO @c1, @c2, @c3
WHILE @@FETCH_STATUS = 0
BEGIN
if (select count(1)
from T1
where a1 = @c1
and a2 = @c2
) = 0
INSERT INTO T1
values (@c1, @c2, @c3)
FETCH NEXT FROM MY_cursor INTO @c1, @c2, @c3
END
CLOSE MY_cursor
DEALLOCATE MY_cursor
答案 9 :(得分:0)
我使用 MERGE 查询来填充一个没有重复的表。 我遇到的问题是表中的双键(代码,值), 并且存在查询非常慢 MERGE 执行得非常快(超过 X100)