2012-03-17 19 views
6

Tengo dos tablas SQL Server idénticas (SOURCE y DESTINATION) con muchas columnas en cada una. Quiero insertar en la tabla DESTINATION filas de la tabla SOURCE que no existen ya en la tabla DESTINATION. Defino la igualdad entre las dos filas si todas las columnas coinciden, excepto la marca de tiempo, una columna de conteo y la clave primaria entera. Así que quiero insertar en DESTINATION todas las filas en SOURCE que ya no existen en DESTINATION ignorando el recuento, la marca de tiempo y las columnas de la clave principal.fusionando el contenido de dos tablas sin duplicar el contenido

¿Cómo puedo hacer esto?

Gracias por todas las contribuciones! Elegí usar el comando Merge porque está estructurado para permitir actualizaciones e insertos en una declaración y necesitaba hacer la actualización por separado.

este es el código que funcionó:

Merge 
into DESTINATION as D 
using SOURCE as S 
on ( 
D.Col1 = S.Col1 
and D.Col2 = S.Col2 
and D.Col3 = S.Col3 
) 
WHEN MATCHED 
THEN UPDATE SET D.Count = S.Count 
WHEN NOT MATCHED THEN 
     INSERT (Col1, Col2, Col3, Count, timestamp) 
     VALUES (S.Col1, S.Col2, S.Col3, S.Count, S.timestamp); 

nota: cuando escribí esta pregunta primero llamé a las tablas AAA y BBB. Me editar y cambiar los nombres de AAA a SOURCE Y BBB a DESTINATION para mayor claridad

Respuesta

5

usando Select declaración para este fin desde SQL Server 2008 es obsoleta en lugar de Select Puede utilizar Merge declaración:

ref:

http://technet.microsoft.com/en-us/library/bb510625.aspx http://weblogs.sqlteam.com/peterl/archive/2007/09/20/Example-of-MERGE-in-SQL-Server-2008.aspx

+1

Excelente caso de uso para el comando MERGE. –

+0

¡Gran respuesta! No estaba enterado de MERGE, pero todavía estoy usando 2005 (por unas semanas más), definitivamente lo usaré en el futuro. – richardtallent

+0

Estoy tratando de descubrir cómo usarlo. el ejemplo en la documentación requiere que revise los elementos en la tabla AAA. Creo que usar la selección correcta debería evitar eso. – Barka

5

Algo como esto:

INSERT INTO BBB(id, timestamp, mycount, col1, col2, col3, etc.) 
SELECT id, timestamp, mycount, col1, col2, col3, etc. 
    FROM AAA 
    WHERE 
     NOT EXISTS(SELECT NULL FROM BBB oldb WHERE 
      oldb.col1 = AAA.col1 
      AND oldb.col2 = AAA.col2 
      AND oldb.col3 = AAA.col3 
     ) 

añadir columnas como sea necesario para la cláusula NOT EXISTS.

1

Una solución con buena ol' de moda LEFT JOIN - tenga en cuenta en el ejemplo siguiente, solo la primera fila de BBB se inserta en AAA, porque solo no tiene una fila coincidente en AAA. Reemplazaría col1 y col2 con las columnas reales de las tablas.

> select * from AAA; 
+---------------------+------+------+ 
| timestamp   | col1 | col2 | 
+---------------------+------+------+ 
| 2012-03-17 08:17:22 | 1 | 1 | 
| 2012-03-17 08:17:27 | 1 | 2 | 
| 2012-03-17 08:17:30 | 1 | 3 | 
| 2012-03-17 08:17:32 | 1 | 4 | 
| 2012-03-17 08:17:49 | 2 | 2 | 
| 2012-03-17 08:17:52 | 2 | 3 | 
| 2012-03-17 08:17:54 | 2 | 4 | 
+---------------------+------+------+ 
7 rows in set (0.00 sec) 

> select * from BBB; 
+---------------------+------+------+ 
| timestamp   | col1 | col2 | 
+---------------------+------+------+ 
| 2012-03-17 08:18:16 | 2 | 1 | 
| 2012-03-17 08:18:18 | 2 | 2 | 
| 2012-03-17 08:18:20 | 2 | 3 | 
+---------------------+------+------+ 
3 rows in set (0.00 sec) 

> INSERT INTO AAA 
    SELECT BBB.* FROM BBB 
    LEFT JOIN AAA 
    USING(col1,col2) 
    WHERE AAA.timestamp IS NULL; 

> select * from AAA; 
+---------------------+------+------+ 
| timestamp   | col1 | col2 | 
+---------------------+------+------+ 
| 2012-03-17 08:17:22 | 1 | 1 | 
| 2012-03-17 08:17:27 | 1 | 2 | 
| 2012-03-17 08:17:30 | 1 | 3 | 
| 2012-03-17 08:17:32 | 1 | 4 | 
| 2012-03-17 08:17:49 | 2 | 2 | 
| 2012-03-17 08:17:52 | 2 | 3 | 
| 2012-03-17 08:17:54 | 2 | 4 | 
| 2012-03-17 08:18:16 | 2 | 1 | 
+---------------------+------+------+ 
8 rows in set (0.00 sec) 
+0

USING() no es compatible con MSSQL. IIRC, es una característica de MySQL. Pero sí me gusta su método de unión, la sintaxis es menos detallada pero más limpia que una subconsulta correlacionada. – richardtallent

+0

@richardtallent podría usar ON() en lugar de USING() en MSSQL? – gcbenison

Cuestiones relacionadas