Realizar expresiones regulares (reemplazar) en una consulta SQL
-
02-07-2019 - |
Pregunta
¿Cuál es la mejor manera de reemplazar todos '& amp; lt' con & amp; lt;
en una columna de base de datos dada? Básicamente realice s/<[^;font>/</gi
Notas:
- debe funcionar en MS SQL Server 2000
- Debe ser repetible (y no terminar con
& amp; lt ;;;;;;;;;;
)
Solución
Se requiere algún pirateo, pero podemos hacerlo con LIKE , PATINDEX , LEFT AND RIGHT y good old concatenación de cadenas.
create table test
(
id int identity(1, 1) not null,
val varchar(25) not null
)
insert into test values ('< <- ok, < <- nok')
while 1 = 1
begin
update test
set val = left(val, patindex('%<[^;]%', val) - 1) +
'<' +
right(val, len(val) - patindex('%<[^;]%', val) - 2)
from test
where val like '%<[^;]%'
IF @@ROWCOUNT = 0 BREAK
end
select * from test
Mejor es que esta es una versión independiente de SQL Server y debería funcionar bien.
Otros consejos
Creo que esto se puede hacer mucho más limpio si usa COSAS diferentes :)
create table test
(
id int identity(1, 1) not null,
val varchar(25) not null
)
insert into test values ('< <- ok, < <- nok')
WHILE 1 = 1
BEGIN
UPDATE test SET
val = STUFF( val , PATINDEX('%<[^;]%', val) + 3 , 0 , ';' )
FROM test
WHERE val LIKE '%<[^;]%'
IF @@ROWCOUNT = 0 BREAK
END
select * from test
¿Qué tal:
UPDATE tableName
SET columName = REPLACE(columName , '<', '<')
WHERE columnName LIKE '%lt%'
AND columnName NOT LIKE '%lt;%'
Editar:
Me acabo de dar cuenta de que esto ignorará las columnas con cadenas & amp; lt;
parcialmente correctas.
En ese caso, puede ignorar la segunda parte de la cláusula where y llamar a esto después:
UPDATE tableName
SET columName = REPLACE(columName , '<;', '<')
Este artículo cubre cómo crear una función simple de reemplazo de expresiones regulares que puede usar en SQL 2000 (y 2005 con un simple ajuste) que pueda ayudarlo.
Si el sabor de expresión regular de MSSQL admite una búsqueda anticipada negativa, esa sería la forma correcta de abordar esto.
s/<(?!;)/</gi
capturará todas las instancias de & amp; lt que no estén seguidas de un ; (incluso si no van seguidas de nada, lo que [^;] fallaría) y no captura el siguiente personaje que no sea ; como parte de la partida, eliminando el problema mencionado en los comentarios sobre la pregunta original de que ese personaje se perdió en el reemplazo.
Desafortunadamente, no uso MSSQL, así que no tengo idea de si es compatible con anticipación negativa o no ...
Muy específico para este patrón, pero he hecho algo similar en el pasado:
REPLACE (REPLACE (columnName, '& amp; lt;', '& amp; lt'), '& amp; lt', '& amp; lt;')
ejemplo más amplio (codificar caracteres que pueden ser inapropiados en un atributo TITLE)
REPLACE(REPLACE(REPLACE(REPLACE(
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
columName
-- Remove existing encoding:
, '&', '&')
, '"', '"')
, ''', '''')
-- Reinstate/Encode:
, '&', '&')
-- Encode:
, '"', '"')
, '''', ''')
, ' ', '%20')
, '<', '%3C')
, '>', '%3E')
, '/', '%2F')
, '\', '%5C')