Script para fusionar dos tablas
Este script nos permite fusionar dos tablas que ya comparten algunas columnas. La situación es que tenemos una tabla A con, por ejemplo, 50 columnas y una tabla B con 15, algunas de las cuales ya coinciden con algunas de las 50 columnas de la tabla A.
Con este script podemos realizar una “migración” controlada de la tabla A a la B.
1: – dos variables para meter los nombres de las tablas
2:
3: DECLARE @tabla1 varchar(100)
4: DECLARE @tabla2 varchar(100)
5:
6: – tabla origen
7:
8: SET @tabla1 = N‘tablaOrigen’
9:
10: – tabla a la que vamos a añadir las columnas
11:
12: SET @tabla2 = N‘tablaDestino’
13:
14: – primero la consulta para averiguar las columnas
15:
16: SELECT
17: clmns.name AS [Nombre],
18:
19: usrt.name AS [DataType],
20: ISNULL(baset.name, N‘’) AS [SystemType],
21: CAST(CASE WHEN baset.name IN (N‘nchar’, N‘nvarchar’)
22: AND clmns.max_length <> -1
23: THEN
24: clmns.max_length/2
25:
26: ELSE
27:
28: clmns.max_length END AS int) AS [Length],
29: CAST(clmns.precision AS int) AS [NumericPrecision]
30: – tabla temporal donde vamos a guardar los resultados de la consulta
31: INTO #_DIFFS
32: FROM sys.tables AS tbl
33: INNER JOIN
34: sys.all_columns AS clmns
35: ON clmns.object_id = tbl.object_id
36: LEFT OUTER JOIN
37: sys.types AS usrt
38: ON usrt.user_type_id = clmns.user_type_id
39: LEFT OUTER JOIN
40: sys.types AS baset
41: ON
42: baset.user_type_id = clmns.system_type_id
43: and
44: baset.user_type_id = baset.system_type_id
45: WHERE
46: clmns.name not in
47: (
48:
49: /* discriminamos auqellas columnas que ya existen en nuestra tabla destino */
50: SELECT clmns.name FROM sys.tables as tbl
51: INNER JOIN sys.all_columns AS clmns ON clmns.object_id=tbl.object_id
52: WHERE tbl.[Nombre]=@tabla2
53: )
54: AND
55: – aqui nos ceñimos a ‘dbo’ solamente aunque sería facil
56: – de modificar para configurar el esquema como parámetro
57: (tbl.name=@tabla1 and SCHEMA_NAME(tbl.schema_id)=N‘dbo’)
58: ORDER BY
59: clmns.column_id ASC;
60:
61: – declaramos una serie de variables para el cursor
62: DECLARE @columnName VARCHAR(100)
63: DECLARE @dataType VARCHAR(100)
64: DECLARE @dataLength VARCHAR(100)
65: DECLARE @numPres VARCHAR(100)
66:
67: – y otra variable para un alter table que vamos a usar
68: – para añadir la(s) nueva(s) columna(s) a la tabla destino
69: DECLARE @alterStatement NVARCHAR(1000)
70:
71: – declaramos el cursor para la tabla temporal de antes donde hemos
72: – guardado el resultado de la consulta
73:
74: DECLARE _cursor CURSOR FOR
75: SELECT [Nombre], DataType, Length, NumericPrecision
76: FROM #_DIFFS
77:
78: – abrimos el cursor
79: OPEN _cursor
80: FETCH NEXT FROM _cursor INTO
81: @columnName, @dataType, @dataLength, @numPres
82:
83: WHILE (@@FETCH_STATUS <> -1)
84: BEGIN
85: IF (@@FETCH_STATUS <> -2)
86: BEGIN
87:
88: – en esta variable vamos a ir concatenando una sentencia de sql
89: – para crear un ‘alter table add’ que nos permita añadir la nueva columna con — el tipo adecuado
90:
91: SET @alterStatement = N‘ALTER TABLE ‘ + @tabla2 + N‘ ADD [’
92: + @columnName + ‘] ‘ + @dataType
93:
94:
95: – en el caso de que sea VARCHAR o NVARCHAR, indicamos la precisión
96: – si fuera decimal o Money o cualquier otro tipo con precisión que — – haya — que indicar también habría que hacerlo, pero — queda como ejercicio![]()
97: – por eso vemos si el tipo de dato que tenemos guardado en @datatype
98: – es VARCHAR o NVARCHAR y realizamos la concatenación adecuada
99:
100: IF UPPER(@dataType) = ‘VARCHAR’ OR UPPER(@dataType) = ‘NVARCHAR’
101: BEGIN
102: SET @alterStatement = @alterStatement + ‘(’ + @dataLength + ‘)’
103: END
104:
105:
106: – si se quiere ver la concatenación…
107: – PRINT @alterStatement;
108:
109: – finalmente ejecutamos la sentencia
110:
111: exec sp_executesql @alterStatement;
112:
113: END;
114:
115: – y recogemos la siguiente fila
116:
117: FETCH NEXT FROM tablesize_cursor INTO @columnName, @dataType, @dataLength, @numPres
118: END;
119:
120:
121: – finalmente cerramos y limpiamos el cursor
122: CLOSE tablesize_cursor;
123: DEALLOCATE tablesize_cursor;
124: – tiramos la tabla temporal que hemos usado
125: DROP TABLE #_DIFFS
126:
127:
Este script o uno similar nos puede salvar mucho tiempo cuando tengamos que integrar dos bases de datos diferentes con considerables diferencias entre las tablas de una y otra. Quizás haya otras maneras, como SSIS, pero a mí me gusta tener el control y aquí podemos tener el control al 100 por 100 de una manera sencilla y rápida.
Simplemente parametrizando los nombres de las tablas al principio podemos reutilizar el script en múltiples situaciones. Y la lógica dentro del cursor es muy sencilla de adaptar a cualquier necesidad.
Saludos