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

Откуда:
Сообщений: 760
sql 12.0.5000.0 (X64) + 12.0.5557.0 (X64)
Кажется, что-то подобное уже исправляли в 2012.
Наткнулся случайно, если бы данные были чуть другими, то ошибку не заметил бы и она всплыла бы на боевом сервере.
Чего нужно избегать в таких случаях? Излишние проверки добавлены с целью обойти ошибку, но они не помогли.
Такое впечатление, что оптимизатор развернул запрос настолько, что текстовые функции стали выполняться раньше условий.
Ошибка возникает и при передаче переменной и при передаче поля. С константой ошибки нет, видимо, из-за того, что план другой получается.
Как лучше парсить email меня не интересует.
use	tempdb
go
create	function	dbo.GetEmailDomainDS
(	@sEmail	varchar ( 512 ) )
returns	table
as
return	( with	cte	as
	(	select
			Value=	null
		where
			@sEmail	not	like	'%_@_%._%'
		union	all
		select
			Value=	substring ( @sEmail,	charindex ( '<',	@sEmail )+	1,	charindex ( '>',	@sEmail )-	charindex ( '<',	@sEmail )-	1 )
		where
				@sEmail		like	'%<%_@_%._%>%'
			and	charindex ( '<',	@sEmail )<	charindex ( '>',	@sEmail )
		union	all
		select
			Value=	@sEmail
		where
				@sEmail		like	'%_@_%._%'
			and	@sEmail	not	like	'%<%_@_%._%>%' )
	select
		Value=	right ( Value,	len ( Value )-	charindex ( '@',	Value ) )
	from
		cte
	where
			Value	like	'%_@_%'
		and	charindex ( '@',	Value )<	len ( Value ) )
go
select	*	from	dbo.GetEmailDomainDS ( 'Ivan Ivanov <ii@domain.ru>' )

declare @s varchar(512)='qr@qr.qr'
select 1,* from tempdb.dbo.GetEmailDomainDS ( 'qr@qr.qr' ) -- работает
select 2,* from tempdb.dbo.GetEmailDomainDS ( @s ) -- ошибка
28 авг 18, 12:31    [21655995]     Ответить | Цитировать Сообщить модератору
 Re: Передача переменной в inline UDF с CTE вызывает ошибку  [new]
buser
Member

Откуда: Санкт-Петербург
Сообщений: 4537
tunknown, используй case
28 авг 18, 12:42    [21656015]     Ответить | Цитировать Сообщить модератору
 Re: Передача переменной в inline UDF с CTE вызывает ошибку  [new]
invm
Member

Откуда: Москва
Сообщений: 9349
create	function	dbo.GetEmailDomainDS
(	@sEmail	varchar ( 512 ) )
returns	table
as
return	( with	cte	as
	(	select
			Value=	null
		where
			@sEmail	not	like	'%_@_%._%'
		union	all
		select
		 Value = substring ( @sEmail, t.a + 1, t.b - t.a - 1 )
		from
		 (select nullif(charindex ( '<',	@sEmail ), 0), nullif(charindex ( '>',	@sEmail ), 0)) t(a, b)
		where
		 @sEmail		like	'%<%_@_%._%>%'
		 and	t.a < t.b
		union	all
		select
			Value=	@sEmail
		where
				@sEmail		like	'%_@_%._%'
			and	@sEmail	not	like	'%<%_@_%._%>%' )
	select
		Value=	right ( Value,	len ( Value )-	charindex ( '@',	Value ) )
	from
		cte
	where
			Value	like	'%_@_%'
		and	charindex ( '@',	Value )<	len ( Value ) )
go
28 авг 18, 12:47    [21656018]     Ответить | Цитировать Сообщить модератору
 Re: Передача переменной в inline UDF с CTE вызывает ошибку  [new]
tunknown
Member

Откуда:
Сообщений: 760
buser
tunknown, используй case
Недосмотрел. Спасибо, case сработал в моём простом случае.

Однако, вопрос остаётся. Как избегать этого, если нужно CTE?
28 авг 18, 12:52    [21656030]     Ответить | Цитировать Сообщить модератору
 Re: Передача переменной в inline UDF с CTE вызывает ошибку  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31356
tunknown
С константой ошибки нет, видимо, из-за того, что план другой получается.

Да, с константой сервер пропускает некоторые из union all
Вам нужно поправить ошибку во втором из них:
declare @sEmail varchar(512)='qr@qr.qr'
;with	cte	as
(	
	select
		Value=	substring ( @sEmail,	charindex ( '<',	@sEmail )+	1,	charindex ( '>',	@sEmail )-	charindex ( '<',	@sEmail )-	1 )
	where
			@sEmail		like	'%<%_@_%._%>%'
		and	charindex ( '<',	@sEmail )<	charindex ( '>',	@sEmail )
)
select
	Value=	right ( Value,	len ( Value )-	charindex ( '@',	Value ) )
from
	cte
where
		Value	like	'%_@_%'
	and	charindex ( '@',	Value )<	len ( Value )
28 авг 18, 12:57    [21656036]     Ответить | Цитировать Сообщить модератору
 Re: Передача переменной в inline UDF с CTE вызывает ошибку  [new]
tunknown
Member

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

Так тоже работает. Спасибо.
28 авг 18, 12:59    [21656039]     Ответить | Цитировать Сообщить модератору
 Re: Передача переменной в inline UDF с CTE вызывает ошибку  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31356
tunknown
Однако, вопрос остаётся. Как избегать этого, если нужно CTE?
Хм, при чём тут CTE???
У вас просто ошибка в запросе (достаточно типичная). Вы думаете, что выражение в SELECT не выполняется для тех строк, которые не попадают под условие. А оно может выполняться для любых строк.
28 авг 18, 13:00    [21656041]     Ответить | Цитировать Сообщить модератору
 Re: Передача переменной в inline UDF с CTE вызывает ошибку  [new]
tunknown
Member

Откуда:
Сообщений: 760
alexeyvg
Вы думаете, что выражение в SELECT не выполняется для тех строк, которые не попадают под условие. А оно может выполняться для любых строк.
Да, моя ошибка. Оптимизатор слишком умён стал, о чём и задокументировано.
BOL Select
Logical Processing Order of the SELECT statement
Note that the actual physical execution of the statement is determined by the query processor and the order may vary from this list.

FROM

ON

JOIN

WHERE

GROUP BY

WITH CUBE or WITH ROLLUP

HAVING

SELECT

DISTINCT

ORDER BY

TOP

28 авг 18, 13:17    [21656080]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить