2009-04-12 19 views
10

, así que tengo una base de datos anterior que estoy migrando a una nueva. El nuevo tiene un esquema ligeramente diferente pero más compatible. Además, quiero renumerar todas las tablas desde cero.TSQL: ACTUALIZAR con INSERT INTO SELECT FROM

Actualmente he estado usando una herramienta que escribí que recupera manualmente el registro anterior, lo inserta en la nueva base de datos y actualiza un campo ID v2 en la base de datos anterior para mostrar su ubicación ID correspondiente en la nueva base de datos.

por ejemplo, estoy seleccionando desde MV5.Posts e insertando en MV6.Posts. Al insertar, recupero el ID de la nueva fila en MV6.Posts y lo actualizo en el campo antiguo MV5.Posts.MV6ID.

¿Hay alguna manera de hacerlo ACTUALIZAR mediante INSERTAR EN SELECCIONAR, de modo que no tenga que procesar cada registro manualmente? Estoy usando SQL Server 2005, edición dev.

Respuesta

9

La clave de la migración es hacer varias cosas: En primer lugar, no hacer nada sin una copia de seguridad actual. En segundo lugar, si las claves cambiarán, debe almacenar tanto la antigua como la nueva en la nueva estructura, al menos temporalmente (permanentemente si el campo de clave está expuesto a los usuarios porque pueden estar buscando por él para obtener registros antiguos).

A continuación, debe tener una comprensión profunda de las relaciones con las tablas secundarias. Si cambia el campo clave, todas las tablas relacionadas deben cambiar también. Aquí es donde tener tanto la clave vieja como la nueva guardadas es útil. Si olvida cambiar alguno de ellos, los datos ya no serán correctos y serán inútiles. Entonces este es un paso crítico.

Elija algunos casos de prueba de datos particularmente complejos, asegurándose de incluir uno o más casos de prueba para cada tabla relacionada. Almacene los valores existentes en las tablas de trabajo.

Para iniciar la migración, inserte en la nueva tabla usando una selección de la tabla anterior. Dependiendo de la cantidad de registros, es posible que desee recorrer lotes (no un registro a la vez) para mejorar el rendimiento. Si la nueva clave es una identidad, simplemente coloque el valor de la clave anterior en su campo y deje que la base de datos cree las nuevas claves.

Luego haga lo mismo con las tablas relacionadas. A continuación, utilice el antiguo valor de la clave en la tabla para actualizar los campos de clave externa con algo como:

prueba
Update t2 
set fkfield = newkey 
from table2 t2 
join table1 t1 on t1.oldkey = t2.fkfield 

la migración mediante la ejecución de los casos de prueba y comparar los datos con lo que se ha guardado desde antes de la migración. Es absolutamente crítico probar a fondo los datos de migración o no puede estar seguro de que los datos sean consistentes con la estructura anterior. La migración es una acción muy compleja; Vale la pena tomarse su tiempo y hacerlo de manera metódica y exhaustiva.

0

yo sepa, no se puede actualizar dos tablas diferentes con una sola instrucción SQL

Sin embargo, puede utilizar disparadores para lograr lo que quiere hacer.

2

Lo mejor que puedes hacer es que sé con el output clause. Suponiendo que tiene SQL 2005 o 2008.

USE AdventureWorks; 
GO 
DECLARE @MyTableVar table(ScrapReasonID smallint, 
          Name varchar(50), 
          ModifiedDate datetime); 
INSERT Production.ScrapReason 
    OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate 
     INTO @MyTableVar 
VALUES (N'Operator error', GETDATE()); 

Todavía necesitaría una segunda pasada para actualizar la tabla original; sin embargo, podría ayudar a simplificar su lógica. ¿Necesita actualizar la tabla fuente? Podrías simplemente almacenar las nuevas identificaciones en una tercera tabla de referencias cruzadas.

1

Heh. Recuerdo hacer esto en una migración.

Poner el old_id en la nueva tabla hace que sea más fácil la actualización - puede hacer un insert into newtable select ... from oldtable, - y la subsiguiente "costura" de los registros es más fácil. En la "puntada" actualizará las claves externas de las tablas secundarias en la inserción, haciendo una subselección en la nueva matriz (insert into newchild select ... (select id from new_parent where old_id = oldchild.fk) as fk, ... from oldchild) o insertará hijos y realizará una actualización por separado para reparar las claves externas.

Hacerlo en una sola inserción es más rápido; hacerlo en un paso separado significa que sus insertos no dependen del pedido y pueden volver a hacerse si es necesario.

Después de la migración, puede soltar las columnas old_id o, si tiene un caso donde el sistema heredado expuso los identificadores y los usuarios usaron las claves como datos, puede mantenerlos para permitir la búsqueda de uso basada en old_id.

De hecho, si tiene las claves foráneas definidas correctamente, puede usar systables/information-schema para generar sus instrucciones de inserción.

4

Probablemente la forma más simple sería agregar una columna en MV6.Posts para oldId, luego inserte todos los registros de la tabla anterior en la nueva tabla. Por último, actualizar el viejo juego de mesa en oldid en la nueva tabla con algo como:

UPDATE mv5.posts 
SET newid = n.id 
FROM mv5.posts o, mv6.posts n 
WHERE o.id = n.oldid 

Se puede limpiar y quitar la columna oldid después si querías.

+0

De hecho, creo que es preferible dejar el oldId en la nueva tabla para tener un newId en la tabla anterior, lo que hace que esto sea aún más fácil. – ninesided

0

Hacer una columna en MV6.Post.OldMV5Id

hacer una inserción en MV6.Post elegir .. desde MV5.Post

luego hacer una actualización de MV5.Post.MV6ID

1

¿Hay alguna manera de hacerlo ACTUALIZAR a través de INSERTAR EN SELECCIONAR, para que no tenga que procesar cada registro manualmente?

Dado que no desea hacerlo manualmente , pero automáticamente, crear un disparador en MV6.Posts de manera que se produce en UPDATEMV5.Posts automáticamente cuando se inserta en MV6.Posts.

Y su disparador podría ser algo como,

create trigger trg_MV6Posts 
on MV6.Posts 
after insert 
as 
begin 
    set identity_insert MV5.Posts on 

    update MV5.Posts 
    set ID = I.ID 
    from inserted I 

    set identity_insert MV5.Posts off 
end 
Cuestiones relacionadas