Introducción
El artículo de hoy proviene de un escenario que experimentamos en la práctica hace algún tiempo. Manejamos un sistema de transacciones con tarjeta denominado Postilion, y tuvimos que actualizar los datos en una columna que contenía direcciones IP como parte de la cadena con una nueva dirección IP. Esto era necesario porque la dirección IP del servidor que albergaba la solución normalmente cambiaba debido al cambio o la restauración de datos a un entorno UAT.
Los datos sobre el servidor se almacenaban en las bases de datos y no había forma de actualizarlos desde la aplicación sin ir fila por fila. Por lo tanto, tuvimos que encontrar una solución eficiente utilizando las funciones LEN y SUBSTRING (o REPLACE) de SQL Server.
Reproduciendo el Medio Ambiente
Para esta demostración, reproducimos solo la tabla requerida para mostrar lo que hicimos. Por supuesto, los datos no son los mismos que en producción.
El Listado 1 demuestra cómo creamos y completamos nuestra tabla de ejemplo:
-- Listing 1: Create and Populate Node_Saps Table
create database postilion;
use postilion
go
-- drop table node_saps
create table node_saps (
[node] varchar(50)
,[sap] varchar(50)
,[type] varchar(50)
,[protocol] varchar(50)
,[address] varchar(50)
,[setup_data] varchar(50)
,[secure] varchar(50)
,[max_nr_conn] varchar(50)
,[msg_mode] varchar(50)
,[nr_active_conns] varchar(50)
,[filter_properties] varchar(50)
)
use postilion
go
insert into node_saps values ('EGH01',2,'sink','TCP','10.2.100.42_atm_ghana', 100,'YES',10,'open',5,'intense');
insert into node_saps values ('EGH02',3,'sink','TCP','10.2.100.42_atm_ghana', 120,'YES',10,'open',5,'moderate');
insert into node_saps values ('ENG01',4,'source','TCP','10.2.100.42_atm_nigeria', 175,'YES',40,'open',19,'premium');
insert into node_saps values ('EBF01',6,'sink','TCP','10.2.100.42_atm_burkina', 122,'YES',20,'open',4,'intense');
insert into node_saps values ('EGQ01',7,'sink','TCP','10.2.100.42_atm_equatorial', 200,'YES',10,'open',2,'moderate');
Esta tabla contiene algunas columnas simples. La columna de interés aquí es la dirección columna. Nuestra tarea es cambiar la dirección IP de 10.2.100.42 a 10.2.100.79.
Como se muestra en la Figura 1, los datos almacenados en la columna de dirección no son solo la dirección IP. Es una cadena y la dirección IP es solo una parte de ella. Por lo tanto, no podemos hacer una simple actualización. Cada fila tiene un valor diferente, y debemos aislar el último octeto de la dirección IP y hacer allí el cambio.
Reemplazar parte de una cadena en SQL Server usando la función SUBSTRING()
Para lograr los requisitos de la tarea, usamos dos funciones simples:la función LEN() y la función SUBSTRING(). Proporcionaremos SUBSTRING en SQL Server con un ejemplo.
- El SQL LEN() La función devuelve el número de caracteres en una cadena. Es importante para nuestra solución porque los datos originales estaban algo sucios:no todo en la columna de dirección era una dirección IP. Por lo tanto, debemos asegurarnos de actualizar lo que pretendemos actualizar.
- El servidor SQL SUBSTRING() La función devuelve una parte de una expresión de carácter, binario, texto o imagen en SQL Server. Lo usamos para asegurarnos de que cambiaremos esa parte de la cadena en la columna de dirección que queremos cambiar:la dirección IP real.
El Listado 2 y la Figura 2 muestran el código para visualizar el resultado de reemplazar .42 con .79 en la columna de dirección.
-- Listing 2: Select Statement to Verify Solution
USE postilion
GO
SELECT [node]
,[sap]
,[type]
,[protocol]
,[address]
,substring (address,1,9) + '79' + substring (address,12,20) manrep
,[setup_data]
,[secure]
,[max_nr_conn]
,[msg_mode]
,[nr_active_conns]
,[filter_properties]
FROM [postilion].[dbo].[node_saps]
WHERE len(address) > 10
Nota:generamos una columna calculada. Por lo tanto, podemos comparar los valores originales con los cambios antes de aplicar esos cambios.
Actualizar parte de una cadena en SQL mediante la función REEMPLAZAR()
Podríamos haber hecho esto más simple usando la función REEMPLAZAR(). Reemplaza todas las apariciones de un valor de cadena especificado con otro valor de cadena.
La función REEMPLAZAR devuelve una cadena donde reemplaza una subcadena con otra subcadena.
Eche un vistazo al código en el Listado 3. Obtenemos exactamente el mismo resultado que se muestra en la Figura 2.
-- Listing 3: Select Statement to Verify Solution Using REPLACE()
USE postilion
GO
SELECT [node]
,[sap]
,[type]
,[protocol]
,[address]
,replace(address,'.42','.79') rep
,[setup_data]
,[secure]
,[max_nr_conn]
,[msg_mode]
,[nr_active_conns]
,[filter_properties]
FROM [postilion].[dbo].[node_saps]
WHERE len(address) > 10
Sintaxis para la función SUBSTRING en una instrucción UPDATE
Visualicemos nuestra solución usando la instrucción SELECT. Necesitamos ver dónde hemos incorporado la función LEN() junto con la función SUBSTRING() o la función REPLACE() más sencilla.
El Listado 4 demuestra cómo ejecutamos la instrucción UPDATE. Por seguridad, lo adjuntamos en una transacción. Si algo está mal, podremos revertirlo.
-- Listing 4: UPDATE Statement Using SUBSTRING()
BEGIN TRAN
update [postilion].[dbo].[node_saps]
set address=substring (address,1,9) + '79' + substring (address,12,20)
where substring (address,10,2)= '42' and
len(address) > 10
SELECT * FROM [postilion].[dbo].[node_saps]
--ROLLBACK
--COMMIT
Si estamos satisfechos con los resultados, simplemente nos comprometemos.
Uso de la función SQL REPLACE en una instrucción UPDATE
Podemos lograr los mismos resultados usando la función REEMPLAZAR() en SQL (vea el Listado 5). Esto funciona debido a nuestros datos específicos, ".42" aparece SOLO UNA VEZ en cada fila.
-- Listing 5: UPDATE Statement Using REPLACE()
BEGIN TRAN
update [postilion].[dbo].[node_saps]
set address=replace(address,'.42','.79')
where substring (address,10,2)= '42' and
len(address) > 10
SELECT * FROM [postilion].[dbo].[node_saps]
--ROLLBACK
--COMMIT
Conclusión
Por lo tanto, hemos demostrado cómo reemplazar una parte de algunas cadenas en la columna usando las funciones SUBSTRING y REPLACE. El éxito de la tarea depende de la comprensión adecuada de los datos involucrados. Por supuesto, necesitamos colaborar con los desarrolladores y especialistas que tengan la experiencia necesaria para predecir las implicaciones de cualquier error en una aplicación.
Además, tomamos precauciones:
- Usamos la declaración SELECT y una columna calculada para determinar cómo se verían los resultados finales.
- Adjuntamos nuestra instrucción UPDATE en una transacción para garantizar la reversión opción.
Puede ir más allá al tomar medidas de precaución y hacer una copia de seguridad de la base de datos:
Referencias
- La función LEN()
- La función SUBSTRING()
- La función REEMPLAZAR