Избегайте дубликатов в запросе INSERT INTO SELECT в SQL Server - PullRequest
93 голосов
/ 25 марта 2010

У меня есть следующие две таблицы:

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 (в моем случае это просто "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 утверждений, основанных на некотором условии.

Ответы [ 8 ]

180 голосов
/ 25 марта 2010

Использование 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 менее эффективен. См. эту ссылку для более подробной информации .

31 голосов
/ 25 марта 2010

В MySQL вы можете сделать это:

INSERT IGNORE INTO Table2(Id, Name) SELECT Id, Name FROM Table1

Есть ли в SQL Server что-нибудь подобное?

7 голосов
/ 16 июля 2016

У меня только что была похожая проблема, ключевое слово DISTINCT работает волшебно:

INSERT INTO Table2(Id, Name) SELECT DISTINCT Id, Name FROM Table1
3 голосов
/ 31 июля 2016

В SQL Server вы можете установить для таблицы индекс Уникальный ключ (Столбцы, которые должны быть уникальными)

From sql server right click on the table design select Indexes/Keys

Select column(s) that will be not duplicate , then type Unique Key

3 голосов
/ 14 января 2015

Использование ignore Duplicates для уникального индекса в соответствии с предложением IanC здесь было моим решением для аналогичной проблемы, создав индекс с параметром WITH IGNORE_DUP_KEY

In backward compatible syntax
, WITH IGNORE_DUP_KEY is equivalent to WITH IGNORE_DUP_KEY = ON.

Ссылка: index_option

2 голосов
/ 21 октября 2018

Я недавно столкнулся с той же проблемой ...
Вот что у меня работало в MS SQL server 2017 ...
Первичный ключ должен быть установлен по идентификатору в таблице 2 ...
Столбцы и свойства столбцов должны быть одинаковыми для обеих таблиц. Это будет работать при первом запуске скрипта ниже. Дубликат идентификатора в таблице 1 не будет вставлен ...

Если вы запустите его во второй раз, вы получите

Нарушение ограничения ограничения PRIMARY KEY

Это код:

Insert into Table_2
Select distinct *
from Table_1
where table_1.ID >1
0 голосов
/ 14 ноября 2018

Простого 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 вы хотите сохранить.

0 голосов
/ 30 января 2018

Немного не по теме, но если вы хотите перенести данные в новую таблицу, и возможные дубликаты находятся в исходной таблице , и столбец, возможно, дублированный, не является идентификатором, a GROUP BY сделает:

INSERT INTO TABLE_2
(name)
  SELECT t1.name
  FROM TABLE_1 t1
  GROUP BY t1.name
...