2010-06-08 17 views
7

Necesito tomar datos de una tabla e importarlos a otra tabla. En pseudocódigo, algo como esto:T-SQL para cada alternativa?

For Each row in table1 
If row.personid is in table2 then 
    update table2.row 
Else 
    insert row into table2 
End If 
Next 

¿Cuál es la mejor manera de hacer esto en T-SQL? Según tengo entendido, T-SQL no admite For Each ... Next, entonces, ¿qué alternativas tengo?

+0

¿la tabla uno tiene una fila para cada personid o puede la misma identificación de persona tener varias filas? – Cervo

Respuesta

7

En igualdad de condiciones, las operaciones basadas establecidos son mejores.

update t1 
set t1.x = t2.x 
. 
. 
. 
from table1 t1 
inner join table2 t2 on t1.id = t2.t1id 

then 

insert into table1 
select * from table2 t2 where t2.t1id not in (select table1.id from table1) 
+1

@jvilalta ¿Estás diciendo que cuanto mayor sea el conjunto de datos, más razones tendrás para recorrer cada registro? Tendría que estar en desacuerdo. – Gratzy

+0

No hay más razones, solo que hacer inserciones y actualizaciones en una declaración pone todo esto en una transacción, y si el conjunto de datos es lo suficientemente grande, la transcation podría fallar o se ejecutará por un tiempo prolongado, evitando que otras transacciones refinamiento. – jvilalta

+0

@jvilalta Estoy bastante seguro de que no se ejecutará tanto tiempo ni se necesitarán tantos recursos como recorrer cada registro. – Gratzy

0

Una de las formas más comunes es utilizar cursores. De esta forma, puede revisar cada registro devuelto por su consulta y manejarlo en consecuencia, ya sea con UPDATE o INSERT.

Ver: http://msdn.microsoft.com/en-us/library/ms180169.aspx

+0

Gracias. Vi esto como una opción, pero también leí que esto estaba en contra de las mejores prácticas. Los cursores b/c no son efectivos en la gestión de la memoria, etc. – davemackey

+2

@davemackey Has leído correctamente. ¡No puedo creer que 2 personas hayan sugerido cursores para esto! –

+1

No dispares el messenger, Martin. Los cursores son una respuesta razonable al pseudocódigo proporcionado y, sin conocer más información, puede ser una solución perfectamente adecuada. Depende de cómo se va a utilizar, el tamaño de la tabla, etc. –

4

Se puede usar un cursor para este como han descrito otros. En lo personal me gusta hacer dos declaraciones en una fila de este modo:

UPDATE tbl2 SET field1=tbl1.field1, field2=tbl1.field2 -- etc. 
FROM tb12 
JOIN tbl1 on tbl2.personid = tbl1.personid 

INSERT tbl2 (personid, field1, field2) 
SELECT personid, field1, field2 
FROM tbl1 
WHERE NOT EXISTS (select personid from tbl2 where personid = tbl1.persondid) 
4

haciendo esto en un bucle while es simplemente incorrecto.
para su ubicación, puede usar la nueva instrucción MERGE en el servidor sql 2008.
Aquí hay un simple example sobre cómo hacerlo.

3

Indique TSQL pero no da una versión. Si está en SQL2008, la instrucción Merge debería hacer lo que necesita.

+0

Gracias, lo siento, utilizamos SQL 2008 pero algunos de nuestros DB se están ejecutando en modo de compatibilidad SQL 2005/2000 (software heredado de terceros) – davemackey

+0

Aún podría funcionar. ¿Lo has probado? Editar: ¡Aquí dice que es compatible con el modo de compatibilidad SQL 2005 pero no menciona el problema de 2000! http://msdn.microsoft.com/en-us/library/bb510680.aspx –

4

Si está en SQL Server 2008, entonces la mejor manera de hacerlo es con la instrucción MERGE. Algo así como ...

MERGE INTO target_table t 
USING source_table s 
ON t.personid = s.personid 
WHEN MATCHED THEN 
    UPDATE ... 
WHEN NOT MATCHED THEN 
    INSERT ... 
9

Si está utilizando SQL Server 2008, entonces podría utilizar la instrucción MERGE. Tal vez algo como esto:

MERGE table2 AS t -- target 
USING table1 AS s -- source 
    ON (t.personid = s.personid) 
WHEN MATCHED THEN 
    UPDATE 
    SET second_column = s.second_column, 
     third_column = s.third_column, 
     etc = s.etc 
WHEN NOT MATCHED THEN  
    INSERT (personid, second_column, third_column, etc) 
    VALUES (s.personid, s.second_column, s.third_column, s.etc)