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

Откуда:
Сообщений: 20504
Добрый день!
Натолкнулся на проблему.
Сиквел тупит когда ему подают вложенную в параметр функцию.
Поясню кодом:
DECLARE @subjPersonName nvarchar(255);
DECLARE @Correspondence AS [dbo].[CorrTableType];
SET @subjPersonName='test';
SET @subjPersonName=dbo.Unify_Str(dbo.Unify_Str(@subjPersonName, @Correspondence), @Correspondence);
PRINT @subjPersonName;

Где CorrTableType - таблица типа такой:
CREATE TYPE CorrTableType AS table([Reduced] nvarchar(6), [Full] nvarchar(40));

Unify_Str - Функция с типа такой:
ALTER FUNCTION Unify_Str(@S nvarchar(MAX), @Correspondence CorrTableType READONLY)
RETURNS nvarchar(MAX)
AS
BEGIN
    DECLARE @Result nvarchar(MAX);
    ...
    RETURN @Result;
END;


MS SQL 2008 выдаёт ошибку:
Must declare the scalar variable "@Correspondence".


Хотелось бы обойти данную проблему, так как подобный двойной вызов функции я использую в селекте, например так:
    SELECT @idSubjExt=[IdSubj] 
    FROM ws.[Person] WITH (nolock) 
    WHERE dbo.Unify_Str(dbo.[PersonName]([LastName], [FirstName], [Patronymic], [BirthDate], [idSex]), @Correspondence)=@subjPersonName 

Где, естественно, тоже не работает
19 сен 12, 13:01    [13188277]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с вложенными функциями  [new]
iap
Member

Откуда: Москва
Сообщений: 47083
defragmentator,

а почему он тупит?
В документации же так и написано: в параметре могут быть только поля таблиц, переменные и литеральные константы.
Вместо скалярной UDF имеет смысл сделать inline table-valued UDF, поставить её во FROM, а в WHERE написать условие для её поля.
19 сен 12, 13:13    [13188368]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с вложенными функциями  [new]
WarAnt
Member

Откуда: Питер
Сообщений: 2423
defragmentator,

адищевое извращение, очередная попытка сделать из сиквела ООП?:))

а по вопросу, текст вашего типа CorrTableType нужно самому придумать?
19 сен 12, 13:23    [13188435]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с вложенными функциями  [new]
defragmentator
Member

Откуда:
Сообщений: 20504
WarAnt
defragmentator,

адищевое извращение, очередная попытка сделать из сиквела ООП?:))

а по вопросу, текст вашего типа CorrTableType нужно самому придумать?


Читайте выше
CREATE TYPE CorrTableType AS table([Reduced] nvarchar(6), [Full] nvarchar(40));


А по-вашему, сиквел - тупой выродок по определению?
19 сен 12, 13:25    [13188460]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с вложенными функциями  [new]
iap
Member

Откуда: Москва
Сообщений: 47083
defragmentator
А по-вашему, сиквел - тупой выродок по определению?
Наоборот, он работает с целыми множествами.
А Вы пытаетесь что-то делать с каждым элементом множества в отдельности.
Не взлетит.
19 сен 12, 13:28    [13188489]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с вложенными функциями  [new]
defragmentator
Member

Откуда:
Сообщений: 20504
iap
он работает с целыми множествами.
А Вы пытаетесь что-то делать с каждым элементом множества в отдельности.
Не взлетит.

Я как раз и пытаюсь выбрать из обычной таблицы те записи, которые удовлетворяют заданному условию для её полей. Проще некуда.
Условие можно задать как суперпозиция двух уже имеющихся функций.
Можно конечно, написать ещё одну функцию, как суперпозицию двух, но хотелось бы сначала услышать диагноз.
19 сен 12, 13:39    [13188600]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с вложенными функциями  [new]
defragmentator
Member

Откуда:
Сообщений: 20504
если Вас смущает таблица @Correspondence, то она просто хранит данные, как параметры функции, обрабатывающей условие выборки, то есть, величина постоянная.
19 сен 12, 13:42    [13188636]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с вложенными функциями  [new]
iap
Member

Откуда: Москва
Сообщений: 47083
defragmentator
iap
он работает с целыми множествами.
А Вы пытаетесь что-то делать с каждым элементом множества в отдельности.
Не взлетит.

Я как раз и пытаюсь выбрать из обычной таблицы те записи, которые удовлетворяют заданному условию для её полей. Проще некуда.
Условие можно задать как суперпозиция двух уже имеющихся функций.
Можно конечно, написать ещё одну функцию, как суперпозицию двух, но хотелось бы сначала услышать диагноз.
У Вас в WHERE ограничение накладывается на результат вызова скалярной функции.
Значит, функция будет вызвана отдельно для каждой из ста миллионов строк.
А у Вас их несколько

Об индексах, если они есть, вообще молчу - ведь индексы бывают только по полям таблиц, но не по результатам вызовов функции.
Так что Вы не то пытаетесь сделать. У SQL есть своя специфика.
19 сен 12, 13:44    [13188673]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с вложенными функциями  [new]
defragmentator
Member

Откуда:
Сообщений: 20504
iap
defragmentator
пропущено...

Я как раз и пытаюсь выбрать из обычной таблицы те записи, которые удовлетворяют заданному условию для её полей. Проще некуда.
Условие можно задать как суперпозиция двух уже имеющихся функций.
Можно конечно, написать ещё одну функцию, как суперпозицию двух, но хотелось бы сначала услышать диагноз.
У Вас в WHERE ограничение накладывается на результат вызова скалярной функции.
Значит, функция будет вызвана отдельно для каждой из ста миллионов строк.
А у Вас их несколько

Об индексах, если они есть, вообще молчу - ведь индексы бывают только по полям таблиц, но не по результатам вызовов функции.
Так что Вы не то пытаетесь сделать. У SQL есть своя специфика.


По Вашему, функцию нельзя использовать в WHERE вообще ?
Я так понял смысл Вашего поста.
А WHERE, насколько я понимаю, для каждой записи проверяется один раз, независимо, от количества вложенных функций.
Да и вообще, проблема тут не в том, как строить запрос, а в том, что суперпозиция нескольких функций в сиквеле работает некорректно - см. пример с SET.
19 сен 12, 15:15    [13189739]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с вложенными функциями  [new]
iap
Member

Откуда: Москва
Сообщений: 47083
defragmentator
По Вашему, функцию нельзя использовать в WHERE вообще ?
Формально можно.
Выглядит ужасно.
19 сен 12, 15:24    [13189832]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с вложенными функциями  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723


Прикольное ограничение, молодцы из M$, ибо нефиг скалярки писать.
Долой империтивистов!
19 сен 12, 15:57    [13190228]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с вложенными функциями  [new]
iap
Member

Откуда: Москва
Сообщений: 47083
iap
defragmentator,

а почему он тупит?
В документации же так и написано: в параметре могут быть только поля таблиц, переменные и литеральные константы.
Вместо скалярной UDF имеет смысл сделать inline table-valued UDF, поставить её во FROM, а в WHERE написать условие для её поля.
Что-то я погорячиился. Извините.
Вызывать в параметре одной скалярной UDF другую скалярную UDF можно:
USE tempdb;
GO
CREATE FUNCTION dbo.F(@X INT) RETURNS INT AS BEGIN RETURN @X*@X; END;
GO
DECLARE @Y INT=5;
SELECT dbo.F(dbo.F(@Y));
GO
DROP FUNCTION dbo.F;
GO
А если есть табличные параметры, то так не работает. Глюк?
19 сен 12, 16:35    [13190637]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с вложенными функциями  [new]
defragmentator
Member

Откуда:
Сообщений: 20504
iap
А если есть табличные параметры, то так не работает. Глюк?

Да, глюк именно с табличным параметром.
19 сен 12, 16:45    [13190757]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с вложенными функциями  [new]
invm
Member

Откуда: Москва
Сообщений: 9719
Это не глюк, а обычный баг, который, скорее всего, будет квалифицирован MS как "by design".
Обойти можно сделав функцию инлайновой или, в крайнем случае, табличной
use tempdb;
go

create type dbo.TestType as table
(
 i int not null
);
go

create function dbo.fnTestFunctionI
(
 @v int,
 @t dbo.TestType readonly
)
returns table
as
 return select @v + max(i) as result from @t;
go

create function dbo.fnTestFunctionTV
(
 @v int,
 @t dbo.TestType readonly
)
returns @r table (result int)
as
begin
 insert into @r
  select @v + max(i) from @t;
 
 return;
end;
go

declare @t dbo.TestType;
insert into @t values (1);

select
 r2.result
from
 dbo.fnTestFunctionI(1, @t) r1 cross apply
 dbo.fnTestFunctionI(r1.result, @t) r2;

select
 r2.result
from
 dbo.fnTestFunctionTV(1, @t) r1 cross apply
 dbo.fnTestFunctionTV(r1.result, @t) r2;
go

drop function dbo.fnTestFunctionI;
drop function dbo.fnTestFunctionTV;
drop type dbo.TestType;
go
19 сен 12, 16:58    [13190906]     Ответить | Цитировать Сообщить модератору
 Re: Проблема с вложенными функциями  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
invm
Обойти можно сделав функцию инлайновой
Чего все мы тут, включая M$ и добиваемся.
19 сен 12, 18:53    [13191506]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить