Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Имитация регулярных выражений на SQL2008. Помогите превратить говнокод в пирожное.  [new]
_Промешан_
Member

Откуда:
Сообщений: 970
В общем в спойлере некий говнокод за 10 минут, которые выполняет имитацию регулярок, при этом большего не требуется от него, однако хочется сделать красиво, по возможности без циклов.
И заодно спросить, не слишком ли OLE-шные приблуды грузятся долго, если делать CLR?

+
ALTER FUNCTION [dbo].[ReplaceByRegEx_f](@text varchar(2048),@RegEx varchar(200)) 
RETURNS varchar(2048)
AS
BEGIN
	/*
		Regext pattern: expr1=repl1|expr2=repl2|
		Example: 'asdg109,6d' need 109.6 => RegEx: asdg=|d=|,=.|  //  | - разделитель.  = - знак равенства
		--select dbo.ReplaceByRegEx('asdg100,6d','asdg=|d=|,=.|')
	*/
	if right(@RegEx,1) != '|' 
	  set @RegEx = @RegEx + '|'

	declare @v varchar(50),@e1 smallint,@e2 smallint, @r1 smallint,@r2 smallint, @one varchar (100)='', @next smallint


	while LEN(@RegEx) > 0 
	begin
		set @next = CHARINDEX('|',@RegEx)
		set @one = Substring(@RegEx,1,@next)
		set @e1 = 1
		set @e2 = charindex('=',@one)-1
		set @r1 = charindex('=',@one)+1
		set @r2 = charindex('|',@one)-1
		if @r2 < @r1
			set @text = replace(@text,substring(@one,@e1,@e2),'')
		else	
			set @text = replace(@text,substring(@one,@e1,@e2),substring(@one,@r1,@r2-@r1+1))
		set @RegEx = RIGHT(@RegEx,Len(@RegEx)-@next)
	end

	
	RETURN @text

END
6 фев 13, 15:01    [13884949]     Ответить | Цитировать Сообщить модератору
 Re: Имитация регулярных выражений на SQL2008. Помогите превратить говнокод в пирожное.  [new]
Ken@t
Member

Откуда: 大地
Сообщений: 3265
_Промешан_,

RegExp можно CLR сделать, если допустимо равернуть на продуктиве.
Но наша практика показала, что нет необходимости в этом, как и sp_OA... и xp_cmdshell ... Все задачи использующие это - легко преобразуются в приложения или рабочие роли.
6 фев 13, 15:21    [13885179]     Ответить | Цитировать Сообщить модератору
 Re: Имитация регулярных выражений на SQL2008. Помогите превратить говнокод в пирожное.  [new]
_Промешан_
Member

Откуда:
Сообщений: 970
Ken@t
_Промешан_,

RegExp можно CLR сделать, если допустимо равернуть на продуктиве.
Но наша практика показала, что нет необходимости в этом, как и sp_OA... и xp_cmdshell ... Все задачи использующие это - легко преобразуются в приложения или рабочие роли.
Можете по-подробнее?

И как то за одно в контексте "из говнокода - пирожок"?

Ну может быть хотя бы данный код "причесать".
6 фев 13, 15:24    [13885223]     Ответить | Цитировать Сообщить модератору
 Re: Имитация регулярных выражений на SQL2008. Помогите превратить говнокод в пирожное.  [new]
Ken@t
Member

Откуда: 大地
Сообщений: 3265
ч0 уж там, можно...
Вот например
6 фев 13, 15:46    [13885449]     Ответить | Цитировать Сообщить модератору
 Re: Имитация регулярных выражений на SQL2008. Помогите превратить говнокод в пирожное.  [new]
_Промешан_
Member

Откуда:
Сообщений: 970
Ken@t
ч0 уж там, можно...
Вот например
А если без CLR?

OLE же вообще не быстрая весчь.
6 фев 13, 16:14    [13885700]     Ответить | Цитировать Сообщить модератору
 Re: Имитация регулярных выражений на SQL2008. Помогите превратить говнокод в пирожное.  [new]
Ken@t
Member

Откуда: 大地
Сообщений: 3265
_Промешан_
Ken@t
ч0 уж там, можно...
Вот например
А если без CLR?

OLE же вообще не быстрая весчь.

OLE и CLR - это мягкое и тёплое.
6 фев 13, 16:17    [13885718]     Ответить | Цитировать Сообщить модератору
 Re: Имитация регулярных выражений на SQL2008. Помогите превратить говнокод в пирожное.  [new]
_Промешан_
Member

Откуда:
Сообщений: 970
Ken@t
_Промешан_
пропущено...
А если без CLR?

OLE же вообще не быстрая весчь.

OLE и CLR - это мягкое и тёплое.
Ой да, точно.
6 фев 13, 17:04    [13886074]     Ответить | Цитировать Сообщить модератору
 Re: Имитация регулярных выражений на SQL2008. Помогите превратить говнокод в пирожное.  [new]
dalex1973
Member

Откуда: Польша
Сообщений: 287
Ken@t,
Пирожка не получится, но если Вы фанат TSQL, то как вариант:
Разделяете @Regex и вставляете в таблицу с помощью функции ufnsplit. Примеров масса , например тут
Когда данные разделены, замену делаете рекурсивным CTE.

+
DECLARE @Pattern NVARCHAR (MAX) = 'asdg=|d=|,=.|';



DECLARE @Table TABLE (Id TINYINT IDENTITY(1, 1) PRIMARY KEY,Value NVARCHAR(4000));

INSERT INTO @Table (Value)
VALUES ('asdg109,6d'),('NoChange'),('dasdg,,,d')

DECLARE @Patterns TABLE (Id TINYINT IDENTITY(1, 1) PRIMARY KEY,Source NVARCHAR(255),Dest NVARCHAR(255))


INSERT INTO @Patterns (Source,Dest)
select (select T2.Data from [dbo].ufnSplit(T1.Data,'=') T2 WHERE T2.Id=1),
(select T2.Data from [dbo].ufnSplit(T1.Data,'=') T2 WHERE T2.Id=2)
 from [dbo].ufnSplit(@Pattern,'|') T1
 WHERE T1.Data!=''


;WITH H (Id,Value,Lvl)
AS (
	SELECT T.Id
		,REPLACE(T.Value, P.Source, P.Dest)
		,CAST(1 AS TINYINT)
	FROM @Table T
	CROSS JOIN @Patterns P
	WHERE P.Id = 1
	
	UNION ALL
	
	SELECT H.Id
		,REPLACE(H.Value, P.Source, P.Dest)
		,CAST(Lvl + 1 AS TINYINT)
	FROM H
	INNER JOIN @Patterns P ON P.Id = H.Lvl + 1
	)
SELECT *
FROM [H]
WHERE H.Lvl = (
		SELECT MAX(H2.lvl)
		FROM [H] H2
		WHERE H.Id = H2.Id
		)
ORDER BY [H].Id
6 фев 13, 17:18    [13886188]     Ответить | Цитировать Сообщить модератору
 Re: Имитация регулярных выражений на SQL2008. Помогите превратить говнокод в пирожное.  [new]
_Промешан_
Member

Откуда:
Сообщений: 970
dalex1973,

Хм. Любопытно.
А по плану, что быстрее работает, рекурсивный вариант или цикличный?
6 фев 13, 17:44    [13886360]     Ответить | Цитировать Сообщить модератору
 Re: Имитация регулярных выражений на SQL2008. Помогите превратить говнокод в пирожное.  [new]
aleks2
Guest
_Промешан_
dalex1973,

Хм. Любопытно.
А по плану, что быстрее работает, рекурсивный вариант или цикличный?

Быстрее всего - табличный. Ибо избавляет аж от двух операций: соединение строки и разбор строки.
7 фев 13, 06:30    [13888157]     Ответить | Цитировать Сообщить модератору
 Re: Имитация регулярных выражений на SQL2008. Помогите превратить говнокод в пирожное.  [new]
dalex1973
Member

Откуда: Польша
Сообщений: 287
_Промешан_
dalex1973,

Хм. Любопытно.
А по плану, что быстрее работает, рекурсивный вариант или цикличный?


Делаете inline table-valued function на два параметра как у вас, затем CROSS APPLY к вашей таблице и как следствие переходите от выполнения типа "запись по записи" на уровень сета как принято в TSQL. Либо процедурой тогда ещё быстрее.

Как я уже сказал пирожка не получите, но от г... можно перейти на черный хлеб с тонким слоем масла ;-)
7 фев 13, 11:37    [13889384]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить