En algunas ocasiones es
necesario migrar datos desde una tabla de una base de datos a otra tabla de otra
base de datos diferente. En este caso he considerado que las tablas son iguales pero hay que
tener en cuenta que si son diferentes habrá que tener cuidado con que campos se
migran a que campos, que longitud y tipo tienen estos.
Hay un método algo complicado
pero muy potente que ya se explicó anteriormente que es creando un cursor.
Creamos un cursor que
recorra la tabla de origen y si el registro NO existe en la tabla de destino lo
insertamos con un INSERT-SELECT si ya existe no hacemos nada.
SI la tabla tiene dependencias tendremos que
dar de alta los registros de las tablas dependientes que no existan en el
destino. Buscamos las dependencias de las tablas con sp_help.
sp_help 'dbo.tbclientes'
En la 7ª salida podemos ver las referencias
externas a otras tablas.
Tiene referencias en otras
tablas como tbMunicipios por tanto, si se
va a hacer un INSERT-SELECT de un registro y sólo en ese caso comprobamos antes
si el código del municipio que se va a introducir en nuestra tabla de clientes ya
existe en la tabla de municipios, si es así inserta solo el cliente, en caso
contrario debe insertar también el municipio con un INSERT-SELECT anidado al de
clientes, para el resto de tablas se procede de la misma forma.
Si las tablas referenciadas a su vez tuvieran otras sería necesario ir anidando bucles.
Un ejemplo de cursor y su bucle anidado podría ser
este:
insert into dbo.tbclientes select
* from dbBASE_DATOS_EXTERNA.dbo.tbclientes
--BUCLE DE CLIENTES
--La clave única
es el NIF
begin transaction
-- declaramos las
variables
DECLARE
@NIF as nvarchar(14)
DECLARE
@i as integer --Contador
--Declaración
del cursor.
declare clientes
INSENSITIVE cursor for
--búsqueda de la
clave
select strNIf from dbBASE_DATOS_EXTERNA.dbo.tbclientes
open clientes
--Comienzo del
blucle
SELECT @i = @@CURSOR_ROWS
-- Avanzamos un
registro y cargamos en las variables los valores encontrados en el primer
registro
fetch next from clientes into
@NIF
WHILE @i > 0
BEGIN
SELECT @i = @i - 1
--si el registro ya existe no lo inserto, si no existe count = 0, lo
inserto
IF (select count(*) from dbo.tbclientes where strNIF = @NIF) = 0
--Antes de hacer
el INSER_SELECT definitivo recorremos en bucles
--anidados las
tablas dependientes para
--insertar las
filas necesarias que no estén dadas de alta
--bucle para la
la tabla tbMunicipios
-- AQUÍ IRIA OTRO
CURSOR PARA INSERTAR LA TABLA DE MUNICIPIOS
-- **********************************************************
--fin de bucle
tabla tbMunicipios
--Hacemos un INSERT SELECT de una
tabla a otra.
SELECT * INTO dbBASE_DATOS_EXTERNA.dbo.tbclientes
FROM dbo.tbclientes
WHERE strNIF = @NIF
-- Avanzamos otro registro
fetch
next from clientes into
@NIF
END
-- cerramos el cursor
close clientes
deallocate clientes
commit
Transaction
Pero antes de complicarnos tanto la vida podemos comprobar
si realmente serán necesarios todos esos bucles anidados.
Unas SELECT previas que nos ahorran mucho trabajo
Para evitar meternos en
un código infinito que acabe migrando todas las tablas de la base de datos (lo
más probable en muchas bases de datos) podemos hacer un estudio sobre datos
reales de los datos que habrá que insertar realmente, no sea que perdamos mucho
tiempo en programar bucles por los que luego no pasará nunca. (Aquí también hay
que tener un poco de sentido común)
Select * from dbBASE_DATOS_EXTERNA.dbo.tbClientes
where strNif not
in (Select strNif from DBO.tbClientes)
Con
esta primera select obtenemos todos los clientes de la BBDD_PRUEBA que no
existen en la REAL.
Para
datos anidados tendríamos que hacer esto:
Select * from dbBASE_DATOS_EXTERNA.dbo.tbClientes where
strCMunicipio not in
(select
strCodigoMunicipio from dbo.tbMunicipios)
Select * from dbBASE_DATOS_EXTERNA.dbo.tbClientes where
strTipoVia not in
(select strTipo
from dbo.tbTiposVia)
Select * from dbBASE_DATOS_EXTERNA.dbo.tbClientes where
strFormaPago not in
(select
strFormaPago from dbo.tbFormasPago)
Select * from dbBASE_DATOS_EXTERNA.dbo.tbClientes
where strGrupoComision not
in (select strGrupoComision from
dbo.tbGrupoComision)
Si esta selects no devuelven datos no es
necesario programar los bucles anidados asociados a la tabla en cuestión.
Si alguna de estas selects devolviera datos
habría que anidar un cursor completo dentro del bucle del cursor principal.
Las mismas select para proveedores son estas:
Select * from dbBASE_DATOS_EXTERNA.dbo.tbProveedores where
strNif not in (Select strNif from DBO.tbProveedores)
Select * from dbBASE_DATOS_EXTERNA.dbo.tbProveedores
where strNIF not
in (select strNif from dbo.tbClientes)
En este caso si hay un subbucle pero como
corresponde a la tabla de Clientes lo podemos obviar, en definitiva para
hacerlo correcto podemos anidar el bucle de los clientes dentro del bucle de
los proveedores y dejarlo todo en un único script.
Para evitar problemas primero pasamos el bucle
que mete los clientes pues sabemos que no tiene problemas de tablas
dependientes y luego el de proveedores.
Pero no es necesario complicarse tanto la vida
con cursores ni bucles, hay una forma mucho más sencilla con subselects y con
insert-selects.
Begin tran
INSERT INTO DBO.tbclientes SELECT * FROM dbBASE_DATOS_EXTERNA.dbo.tbClientes WHERE strNif not in (SELECT strNif FROM
DBO.tbClientes)
INSERT INTO DBO.tbProveedores
SELECT * FROM dbBASE_DATOS_EXTERNA.dbo.tbProveedores WHERE strNif not in (SELECT strNif FROM DBO.tbProveedores)
Commit tran
Si todo ha
ido bien, ejecutar commit tran para cerrar la transacción
Para asegurarse de que todo ha ido bien, las selects de
abajo no deberán devolver ningún registro.
--Cuando se ejecute el script estas select no deben
devolver registros
Select * from dbBASE_DATOS_EXTERNA.dbo.tbClientes where strNif not in (Select strNif from dbo.tbClientes)
--selects para los bucles de Clientes
Select * from dbBASE_DATOS_EXTERNA.dbo.tbClientes where strCMunicipio not in (select strCodigoMunicipio from dbo.tbMunicipios)
Select * from dbBASE_DATOS_EXTERNA.dbo.tbClientes where strTipoVia not in (select strTipo from dbo.tbTiposVia)
Select * from dbBASE_DATOS_EXTERNA.dbo.tbClientes where strFormaPago not in (select strFormaPago from dbo.tbFormasPago)
Select * from dbBASE_DATOS_EXTERNA.dbo.tbClientes where strGrupoComision not in (select strGrupoComision from dbo.tbGrupoComision)
--selects para bucles de Proveedores
Select * from dbBASE_DATOS_EXTERNA.dbo.tbProveedores where strNif not in (Select strNif from dbo.tbProveedores)
Select * from dbBASE_DATOS_EXTERNA.dbo.tbProveedores where strNIF not in (select strNif from dbo.tbClientes)
No hay comentarios:
Publicar un comentario