web-dev-qa-db-fra.com

Évitez les doublons dans la requête INSERT INTO SELECT dans SQL Server

J'ai les deux tables suivantes:

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

Table2
----------
ID   Name
1    Z

Je dois insérer des données de Table1 à Table2. Je peux utiliser la syntaxe suivante:

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

Cependant, dans mon cas, des ID en double peuvent exister dans Table2 (dans mon cas, il s'agit simplement de "1") et je ne veux pas copier à nouveau car cela jetterait une erreur. 

Je peux écrire quelque chose comme ça:

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

Y a-t-il une meilleure façon de faire cela sans utiliser IF - ELSE? Je veux éviter deux instructions INSERT INTO-SELECT basées sur une condition.

88
Ashish Gupta

Utiliser 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)

Utiliser 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)

Utiliser 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

Parmi les trois options, le LEFT JOIN/IS NULL est moins efficace. Voir ce lien pour plus de détails .

171
OMG Ponies

Dans MySQL, vous pouvez faire ceci:

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

SQL Server a-t-il quelque chose de similaire?

27
Duncan

Je viens d'avoir un problème similaire, le mot clé DISTINCT fonctionne comme par magie:

INSERT INTO Table2(Id, Name) SELECT DISTINCT Id, Name FROM Table1
6
Hunter Bingham

Utiliser ignore Duplicates sur l'index unique comme suggéré par IanC ici était ma solution pour un problème similaire, créer l'index avec l'option WITH IGNORE_DUP_KEY

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

Réf .: index_option

3
Tazz602

A partir de SQL Server, vous pouvez définir un index Unique key sur la table pour (Colonnes devant être uniques).

 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
M. Salah

Je faisais face au même problème récemment ...
Voici ce qui a fonctionné pour moi dans MS SQL Server 2017 ...
La clé primaire doit être définie sur ID dans le tableau 2 ...
Les colonnes et les propriétés de colonne doivent bien sûr être les mêmes entre les deux tables. Cela fonctionnera la première fois que vous exécuterez le script ci-dessous. Le duplicata de la table 1 ne sera pas inséré ...

Si vous le lancez une deuxième fois, vous aurez un 

Violation de l'erreur de contrainte PRIMARY KEY

C'est le code:

Insert into Table_2
Select distinct *
from Table_1
where table_1.ID >1
2
Vishane Naicker

Un simple DELETE avant le INSERT suffirait:

DELETE FROM Table2 WHERE Id = (SELECT Id FROM Table1)
INSERT INTO Table2 (Id, name) SELECT Id, name FROM Table1

Changez Table1 pour Table2 en fonction des paires Id et name que vous souhaitez conserver.

0
Sacro

Un peu hors sujet, mais si vous voulez migrer les données vers une nouvelle table et que les doublons possibles se trouvent dans la table original, et que la colonne éventuellement dupliquée n'est pas un identifiant, un GROUP BY fera:

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