Hoy me ha surgido la necesidad de cambiar el valor de un código de producto en toda las tablas de la base de datos. Es decir, donde antes tenía el código X ahora debería de tener el código Y.
Lógicamente podría ejecutar manualmente una sentencia de actualización por cada tabla de la base de datos donde se encuentra el campo, pero coincidiremos ambos en que esto no parece una solución muy elegante. Además, no tengo la seguridad de saber exactamente en que tablas está mi campo y no quiero dejar el proceso a medias.
Como me parece que esta situación se podría repetir en un futuro, tanto para el código del producto como para cualquier otro código, he resuelto escribir un script que automatice la tarea en la medida de lo posible.
A grandes rasgos, el script que te muestro a continuación lleva a cabo los siguientes pasos:
- Declarar el nombre de campo que queremos actualizar (aquí cabe mencionar que una base de datos normalizada ayudaría al proceso, es decir, si en una tabla has llamado a tu código de producto “ProductID” y en otra “IDProducto”, pues estamos fastidiados…)
- Declarar el valor que queremos sustituir y el nuevo valor que queremos utilizar.
- Recorrer las tablas en las que aparece el nombre de campo y deshabilitar todas sus restricciones (imagina que sino las restricciones del tipo ‘foreign key’ impedirían el proceso de actualización masivo)
- Ejecutar una consulta de actualización por cada tabla donde aparezca el campo.
- Volver a habilitar las restricciones previamente deshabilitadas.
Lógicamente el script no es perfecto y requiere cambiar algunos ajuste manuales como el tipo de los parámetros, tanto en la declaración inicial como en la sentencia de actualización con sp_executesql.
Además, el script presupone que las ‘foreign key’ declaradas en tus tablas están todas activadas, porque sino y en el último paso, siempre las activará incondicionalmente con independencia de como estuvieran inicialmente.
A continuación el script y espero te sea útil:
DECLARE @columnName SYSNAME-- Nombre de campoSET @columnName = N'ProductID'DECLARE @OldValue NVARCHAR(20)-- Valor antiguoSET @OldValue = N'1701291'DECLARE @NewValue NVARCHAR(20)-- Valor nuevoSET @NewValue = N'1701291__MODIFICADO'DECLARE @tableSchema NVARCHAR(128)DECLARE @tableName SYSNAMEDECLARE @noCheckStatement NVARCHAR(4000)DECLARE @checkStatement NVARCHAR(4000)SET @noCheckStatement = N''SET @checkStatement = N''-- Tablas que contienen el nombre de campoDECLARE cTables CURSOR READ_ONLYFORSELECT T.TABLE_SCHEMA ,T.TABLE_NAMEFROM INFORMATION_SCHEMA.TABLES TINNER JOIN INFORMATION_SCHEMA.COLUMNS CON T.TABLE_SCHEMA = C.TABLE_SCHEMA AND T.TABLE_NAME = C.TABLE_NAMEWHERE TABLE_TYPE = N'BASE TABLE'AND COLUMN_NAME = @columnNameOPEN cTablesFETCH NEXT FROM cTables INTO @tableSchema, @tableNameWHILE ( @@fetch_status <> -1 )BEGINIF ( @@fetch_status <> -2 )BEGIN-- Generar sentencias para deshabilitar y habilitar restriccionesSET @noCheckStatement = @noCheckStatement + N'ALTER TABLE '+ @tableSchema + '.' + @tableName+ ' NOCHECK CONSTRAINT ALL;'SET @checkStatement = @checkStatement + N'ALTER TABLE '+ @tableSchema + '.' + @tableName+ ' WITH CHECK CHECK CONSTRAINT ALL;'ENDFETCH NEXT FROM cTables INTO @tableSchema, @tableNameENDCLOSE cTables-- Deshabilitar restriccionesEXECUTE sp_executesql @noCheckStatementDECLARE @statement NVARCHAR(4000)DECLARE @params NVARCHAR(4000)OPEN cTablesFETCH NEXT FROM cTables INTO @tableSchema, @tableNameWHILE ( @@fetch_status <> -1 )BEGINIF ( @@fetch_status <> -2 )BEGIN-- Generar sentencia de actualizaciónSET @statement = N'UPDATE ' + @tableSchema + '.' + @tableName+ ' SET ' + @columnName + ' = @NewValue WHERE '+ @columnName + ' = @OldValue'SET @params = N'@NewValue NVARCHAR(20), @OldValue NVARCHAR(20)'-- ActualizarEXECUTE sp_executesql @statement, @params, @NewValue,@OldValueENDFETCH NEXT FROM cTables INTO @tableSchema, @tableNameENDCLOSE cTablesDEALLOCATE cTables-- Habilitar restriccionesEXECUTE sp_executesql @checkStatement
No hay comentarios:
Publicar un comentario