Замена множественному REPLACE или изящные решения

Замена множественному REPLACE или изящные решенияИногда встаёт задача почистить строки от лишних символов. Если это 1-2 символа, то мы легко и не принуждённо воспользуемся функцией REPLACE, но при необходимости заменить большее количество символов, такое решение не будет изящным.

 

 

Вот примерно так выглядит множественный REPLACE. Согласитесь, данное решение совсем не читаемо.

SELECT  F_C_DATA_GR.NDF_CODE, 
	(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(
	replace(replace(replace(replace(replace(replace(f_c_data_gr.NAME + ISNULL(f_c_data_gr.FORM, '') + ISNULL(f_c_data_gr.MANUFACTURER, '') + CAST(F_C_DATA_GR.PRICE AS varchar(15))
, '.', ''), ',', ''), '_', ''), '  ', ''), ' ', ''), '|', ''), '№', 'N'), '-', ''), 'і', 'и'), '/', ''), '##', ''), '#', ''), '(', ''), ')', ''), '"', ''), '@', '')
, '$', ''), '**', ''), '%', ''), '+', ''), '*', ''), '=', ''), '~', '')) n
 FROM          F_C_DATA_GR

 

Тут нам на помощь могут придти следующие методы:

Метод 1 (функция):

Создаём функцию, куда будем передавать строку и необходимые символы для замены:

create function [dbo].[Split](@String varchar(8000), @Delimiter char(1)) 
returns @temptable TABLE (items varchar(8000)) 
as 
begin 
declare @idx int 
declare @slice varchar(8000)

select @idx = 1 
if len(@String)<1 or @String is null return

while @idx!= 0 
begin 
set @idx = charindex(@Delimiter,@String) 
if @idx!=0 
set @slice = left(@String,@idx - 1) 
else 
set @slice = @String

if(len(@slice)>0) 
insert into @temptable(Items) values(@slice)

set @String = right(@String,len(@String) - @idx) 
if len(@String) = 0 break 
end 
return 
end

 

Вызываем функцию:

DECLARE @NEWSTRING VARCHAR(100) 
SET @NEWSTRING = '(N_100-(6858)*(6858)*N_100/0_2)%N_35' ;
SELECT @NEWSTRING = REPLACE(@NEWSTRING, items, '~') FROM dbo.Split('+,-,*,/,%,(,)', ',');
PRINT @NEWSTRING

 

На выходе будет следующее:

~N_100~~6858~~~6858~~N_100~0_2~~N_35

 

Вывод: Данный метод не самый лучший, так как имеет проблемы с производительностью и со встраиваемостью в запрос.

 

Метод 2 (функция, встраиваемая в запрос):

Создаём функцию:

CREATE FUNCTION StringReduce
      (
      @inputstr VARCHAR(4096)
      , @stripchrs VARCHAR(255)
      )
RETURNS VARCHAR(4096)
AS  
BEGIN 
      DECLARE @charcounter INT
      SET @charcounter = 1
      WHILE  @charcounter <= LEN(@stripchrs)
      BEGIN
            SET @inputstr = REPLACE(@inputstr, SUBSTRING(@stripchrs, @charcounter, 1), '')
            SET @charcounter = @charcounter + 1
      END
RETURN @inputstr
END

 

Создаём временную таблицу, напомняем её данными и встраиваем в запрос:

CREATE TABLE #ManyCharacters
(
name nvarchar(255)
)
INSERT INTO #ManyCharacters VALUES ('ABC!@#%DEFgh')
INSERT INTO #ManyCharacters VALUES ('~!102WXY&*()_Z')

SELECT dbo.StringReduce(name, '@#$^&*()-+_!%~') FROM #ManyCharacters 

DROP TABLE #ManyCharacters

 

Вывод: Данный метод уже можно использовать при выборке из таблицы, но в теории, скорость работы данного метода ещё не оптимальный

 

Метод 3 (CTE — обобщённое табличное выражение):

Создаём временную таблицу и заполняем её данными. Именно данная таблица будет использоваться в CTE:

CREATE TABLE #Foobar (
  key_col INT PRIMARY KEY,
  text_col NVARCHAR(100));

INSERT INTO #Foobar VALUES (1, N'ABC!@#%DEFgh');
INSERT INTO #Foobar VALUES (2, N'~!102WXY&*()_Z');

 

Создаём CTE (в нашем случае мы заменяем символы на пустое место, можно заменять на любое значение, для этого необходимо немного модифицировать CTE):

WITH Clean (key_col, text_col, ch) 
AS
(SELECT key_col,
        REPLACE(text_col, CHAR(255), ''),
        255
 FROM #Foobar
 UNION ALL
 SELECT key_col,
        CASE WHEN
             CHAR(ch - 1) NOT LIKE '[A-Z!]'
             THEN REPLACE(text_col, CHAR(ch - 1), '')
             ELSE text_col END,
        ch - 1
 FROM Clean
 WHERE ch > 1)

 

Делаем выбоорку и удаляем временную таблицу:

SELECT key_col, text_col 
FROM Clean
WHERE ch = 1
OPTION (MAXRECURSION 255);

DROP TABLE #Foobar

 

Вывод: Данный метод, на мой взгляд, менее удобный, но подразумевается, что работает быстрее.

 

Метод 4 (dll):

Так же можно написать dll, подключить её и с помощью программирования обработать все необходимые символы.

Вывод: Данный метод будет максимально быстрым.

 

Более подробно про CTE (обобщённое табличное выражение)

 

Запись опубликована в рубрике В помощь администратору с метками , , . Добавьте в закладки постоянную ссылку.

Добавить комментарий

Войти с помощью: