Выполните регулярное выражение (замену) в SQL-запросе
-
02-07-2019 - |
Вопрос
Каков наилучший способ заменить все '<' на <
в заданном столбце базы данных?В основном выполняют s/<[^;]/</gi
Примечания:
- должен работать в MS SQL Server 2000
- Должно быть повторяемым (и не заканчиваться
<;;;;;;;;;
)
Решение
Требуется некоторый взлом, но мы можем сделать это с помощью Нравится, ПАТИНДЕКС, СЛЕВА И ПРАВИЛЬНО и старая добрая конкатенация строк.
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
Лучше то, что это не зависит от версии SQL Server и должно работать просто отлично.
Другие советы
Я думаю, это можно сделать намного чище, если вы используете другие МАТЕРИАЛЫ :)
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
Как насчет:
UPDATE tableName
SET columName = REPLACE(columName , '<', '<')
WHERE columnName LIKE '%lt%'
AND columnName NOT LIKE '%lt;%'
Редактировать:
Я только что понял, что это будет игнорировать столбцы с частично корректными <
струны.
В этом случае вы можете проигнорировать вторую часть предложения where и вызвать это позже:
UPDATE tableName
SET columName = REPLACE(columName , '<;', '<')
Эта статья описывается, как создать простую функцию замены регулярных выражений, которую вы можете использовать в SQL 2000 (и 2005 с простой настройкой) и которая может вам помочь.
Если вкус регулярных выражений MSSQL поддерживает отрицательный прогноз, это был бы Правильный подход к этому.
s/<(?!;)/</gi
будет перехватывать все экземпляры < за которыми не следует ; (даже если за ними ничего не следует, что [^;] пропустил бы) и не фиксирует следующие не-; персонаж как часть соответствия, устраняющая проблему, упомянутую в комментариях к исходному вопросу о том, что этот персонаж был потерян при замене.
К сожалению, я не использую MSSQL, поэтому понятия не имею, поддерживает ли он отрицательный прогноз или нет...
Очень специфично для этого шаблона, но я делал подобное в прошлом:
REPLACE(REPLACE(columName, '<', '<'), '<', '<')
более широкий пример (кодирование символов, которые могут быть неуместны в атрибуте TITLE)
REPLACE(REPLACE(REPLACE(REPLACE(
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
columName
-- Remove existing encoding:
, '&', '&')
, '"', '"')
, ''', '''')
-- Reinstate/Encode:
, '&', '&')
-- Encode:
, '"', '"')
, '''', ''')
, ' ', '%20')
, '<', '%3C')
, '>', '%3E')
, '/', '%2F')
, '\', '%5C')