Evitar duplicados en INSERTAR EN SELECCIONAR consulta en SQL Server


Tengo las siguientes dos tablas:

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

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

Necesito insertar datos de Table1 a Table2. Puedo usar la siguiente sintaxis:

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

Sin embargo, en mi caso, los ID duplicados podrían existir en Table2 (en mi caso, es solo "1") y no quiero copiar eso de nuevo, ya que lanzaría un error.

Puedo escribir algo como esto:

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

¿Hay una mejor manera de hacer esto sin usar IF - ELSE? Quiero evitar dos declaraciones INSERT INTO-SELECT basadas en alguna condición.

Author: Pang, 2010-03-25

6 answers

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

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

Usando 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

De las tres opciones, la LEFT JOIN/IS NULL es menos eficiente. Vea este enlace para más detalles.

 159
Author: OMG Ponies,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-25 05:07:34

En MySQL puedes hacer esto:

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

¿Tiene SQL Server algo similar?

 26
Author: Duncan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-25 06:54:22

Acabo de tener un problema similar, la palabra clave DISTINTA funciona mágica:

INSERT INTO Table2(Id, Name) SELECT DISTINCT Id, Name FROM Table1
 6
Author: Hunter Bingham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-15 22:27:07

Usar ignore Duplicates en el índice único como sugirió IanC aquí fue mi solución para un problema similar, creando el índice con la opción WITH IGNORE_DUP_KEY

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

Ref.: index_option

 3
Author: Tazz602,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:26

Desde SQL Server puede establecer un índice Clave única en la tabla para (Columnas que deben ser únicas)

Desde sql server haga clic derecho en el diseño de la tabla seleccione Índices / Claves

Seleccione la (s) columna (s) que no se duplicarán y, a continuación, escriba Clave única

 3
Author: M. Salah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-31 08:09:14

Un poco fuera de tema, pero si desea migrar los datos a una nueva tabla, y los posibles duplicados están en la tabla original, y la columna posiblemente duplicada no es un id, a GROUP BY hará:

INSERT INTO TABLE_2
(name)
  SELECT t1.name
  FROM TABLE_1 t1
  GROUP BY t1.name
 0
Author: FullStackFool,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-30 15:43:17