Introdução
O artigo de hoje vem de um cenário que vivenciamos na prática há algum tempo. Gerenciamos um sistema de transações com cartão chamado Postilion e tivemos que atualizar os dados em uma coluna contendo endereços IP como parte da string com um novo endereço IP. Isso foi necessário porque o endereço IP do servidor que hospeda a solução normalmente mudaria devido à alternância ou à restauração de dados para um ambiente UAT.
Os dados sobre o servidor eram armazenados nos bancos de dados, e não havia como atualizar os mesmos da aplicação sem ir linha por linha. Assim, tivemos que encontrar uma solução eficiente usando as funções LEN e SUBSTRING (ou REPLACE) do SQL Server.
Reproduzindo o Meio Ambiente
Para esta demonstração, reproduzimos apenas a tabela necessária para mostrar o que fizemos. Claro, os dados não são os mesmos que na produção.
A Listagem 1 demonstra como criamos e preenchemos nossa tabela de exemplo:
-- 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 tabela contém algumas colunas simples. A coluna de interesse aqui é o endereço coluna. Nossa tarefa é alterar o endereço IP de 10.2.100.42 para 10.2.100.79.
Conforme mostrado na Figura 1, os dados armazenados na coluna de endereço não são apenas o endereço IP. É uma string e o endereço IP é apenas uma parte dela. Portanto, não podemos fazer uma atualização simples. Cada linha tem um valor diferente, e devemos isolar o último octeto do endereço IP e fazer a alteração nele.
Substituir parte de uma string no SQL Server usando a função SUBSTRING()
Para atingir os requisitos da tarefa, usamos duas funções simples:a função LEN() e a função SUBSTRING(). Forneceremos SUBSTRING no SQL Server com exemplo.
- O SQL LEN() função retorna o número de caracteres em uma string. É importante para nossa solução porque os dados originais estavam um pouco sujos – nem tudo na coluna de endereço era um endereço IP. Assim, devemos garantir a atualização do que pretendíamos atualizar.
- O SQL Server SUBSTRING() A função retorna uma parte de uma expressão de caractere, binário, texto ou imagem no SQL Server. Usamos isso para garantir que alteraremos a parte da string na coluna de endereço que queremos alterar - o endereço IP real.
A Listagem 2 e a Figura 2 mostram o código para visualizar o resultado da substituição de .42 por .79 na coluna de endereço.
-- 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:Geramos uma coluna computada. Assim, podemos comparar os valores originais com as alterações antes de aplicar essas alterações.
Atualizar parte de uma string em SQL usando a função REPLACE()
Poderíamos ter feito isso de forma mais simples usando a função REPLACE(). Ele substitui todas as ocorrências de um valor de string especificado por outro valor de string.
A função REPLACE retorna uma string onde substitui uma substring por outra substring.
Dê uma olhada no código na Listagem 3. Obtemos exatamente o mesmo resultado mostrado na 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
Sintaxe para a função SUBSTRING em uma instrução UPDATE
Vamos visualizar nossa solução usando a instrução SELECT. Precisamos ver onde incorporamos a função LEN() junto com a função SUBSTRING() ou a função REPLACE() mais fácil.
A Listagem 4 demonstra como executamos a instrução UPDATE. Por segurança, incluímos em uma transação. Se algo estiver errado, poderemos reverter.
-- 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
Se estivermos satisfeitos com os resultados, simplesmente nos comprometemos.
Usando a função SQL REPLACE em uma instrução UPDATE
Podemos obter os mesmos resultados usando a função REPLACE() no SQL (consulte a Listagem 5). Isso funciona devido aos nossos dados específicos, “.42” ocorre APENAS UMA VEZ em cada linha.
-- 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
Conclusão
Assim, demonstramos como substituir uma parte de algumas strings na coluna usando as funções SUBSTRING e REPLACE. O sucesso da tarefa depende do bom entendimento dos dados envolvidos. Claro, precisamos colaborar com os desenvolvedores e especialistas com a experiência necessária para prever as implicações de quaisquer erros em um aplicativo.
Além disso, tomamos precauções:
- Usamos a instrução SELECT e uma coluna computada para determinar como seriam os resultados finais.
- Incluímos nossa instrução UPDATE em uma transação para garantir a reversão opção.
Você pode ir mais longe na tomada de medidas de precaução e fazer um backup do banco de dados:
Referências
- A função LEN()
- A função SUBSTRING()
- A função REPLACE