2010-03-25 18 views
73

Ho le seguenti due tabelle:evitare duplicati in query di INSERT INTO SELECT SQL Server

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

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

ho bisogno di inserire i dati da Table1 a Table2. Posso utilizzare la seguente sintassi:

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

Tuttavia, nel mio caso, potrebbero esistere ID duplicati in Table2 (nel mio caso, è solo "1") e non voglio copiare che ancora una volta come questo sarebbe lanciare un errore

posso scrivere qualcosa del genere:

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 

Esiste un modo migliore per fare questo senza usare IF - ELSE? Voglio evitare due affermazioni INSERT INTO-SELECT basate su alcune condizioni.

risposta

145

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

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

Utilizzando 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 

Delle tre opzioni, il LEFT JOIN/IS NULL è meno efficiente. Vedi this link for more details.

+3

Ju Per un chiarimento sulla versione NOT EXISTS, avrai bisogno di un suggerimento WITH (HOLDLOCK) o non verranno presi blocchi (perché non ci sono righe da bloccare!) così un altro thread potrebbe inserire la riga sotto di te. – IDisposable

+1

Interessante, perché ho sempre creduto che unirsi per essere più veloce dei sottoseleziona. Forse è solo per i join diretti, e non è applicabile ai join di sinistra. – Duncan

+1

Duncan, l'unione è spesso più veloce che si sottosele quando sono sottoquery correlate. Se si ha la sottoquery nella lista di selezione, un join sarà spesso più veloce. – HLGEM

19

In MySQL si può fare questo:

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

non SQL Server ha nulla di simile?

+4

+1 per avermi istruito su questo. Sintassi molto bella. Decisamente più corto e migliore di quello che ho usato. Sfortunatamente il server Sql non ha questo. –

+12

Non completamente vero. Quando si crea un indice univoco, è possibile impostarlo su "ignora duplicati", nel qual caso SQL Server ignorerà qualsiasi tentativo di aggiungere un duplicato. – IamIC

+1

E SQL Server non può ancora ... patetico. –

3

Utilizzando ignore Duplicates sulla indice univoco as suggested by IanC here era la mia soluzione per un problema simile, creando l'indice con l'opzione WITH IGNORE_DUP_KEY

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

Ref .: index_option

6

Ho appena avuto un problema simile, il DISTINCT keyword works magic:

INSERT INTO Table2(Id, Name) SELECT DISTINCT Id, Name FROM Table1 
+5

A meno che non ti fraintenda totalmente, funzionerà se hai duplicati nel set che stai inserendo _da_. Tuttavia, non sarà di aiuto se il set che stai inserendo potrebbe essere duplicato di dati già nella tabella 'insert into'. – FreeMan

2

Da SQL Server è possibile impostare un Unico chiave indice sul tavolo per (colonne che deve essere unico)

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

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

0

Un po 'fuori tema, ma se si desidera migrare i dati in una nuova tabella, e i possibili duplicati sono nella tabella originale , e la colonna eventualmente duplicato non è un id, un GROUP BY farà:

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