2010-01-05 2 views
21

Почему SQL Server не поддерживает блоки TRY-CATCH внутри UDF?Почему блок TRY-CATCH не разрешен внутри UDF?

Если мы говорим о скалярных UDF, которые в основном используются для вычислений и разговоров, этот блок должен быть сильно использован, но у нас его нет.

Кроме того, какие обходные пути вы используете для этого?

+3

+1 хороший вопрос – kevchadders

ответ

12

UDFs в MSSQL не имеют побочных эффектов, которые BOL определяет как «изменение состояния базы данных». Это довольно расплывчатое описание, но MSSQL, видимо, считает ошибки, чтобы изменить состояние базы данных - это UDF не компилируется:

create function dbo.foo() 
returns int 
as 
begin 
    raiserror('Foo', 16, 1) 
    return 1 
end 
go 

Сообщение об ошибке:

Msg 443, уровень 16, состояние 14 , Процедура foo, Строка 5 Недействительное использование операционного оператора «RAISERROR» внутри функции.

Если считается, что проблема с изменением состояния базы данных связана с изменением состояния базы данных, то, вероятно, захват и обработка одной из них тоже. Я признаю, что это не очень объяснение.

В практическом плане, однако, часто бывает лучше, чтобы вызывающий абонент решал, как обращаться с ошибками в любом случае. Предположим, вы пишете такую ​​функцию:

create function dbo.divide (@x int, @y int) 
returns float 
as 
begin 
return @x/cast(@y as float) 
end 

Как вы справляетесь с случаем, когда приложение проходит ноль для @y? Если вы поймаете деление на нулевое исключение, что вы собираетесь делать дальше? Какое значение вы можете вернуть из функции, которая имеет смысл для вызывающего, учитывая, что вы даже не можете узнать, какое приложение вызывает вашу функцию?

Возможно, вы думаете о возврате NULL, но согласятся ли разработчики приложений с вашей функцией? Все ли их приложения рассматривают деление на нулевую ошибку, чтобы иметь такое же влияние или важность? Не говоря уже о том, что NULL в определенных местах могут полностью изменить результаты запроса, возможно, таким образом, что разработчик приложений вообще не хочет.

Если вы единственный разработчик, возможно, это не проблема, но с большим количеством людей он быстро становится одним.

+1

Я хотел воспроизвести поведение TRY_CAST, написав собственный UDF: –

1

Как работа, я бы назвал UDF из TRY/CATCH внутри хранимой процедуры.

+2

Спасибо за ответ, но когда вы пишете UDF, его обычно повторно используют другие люди. Ваше решение работает, если я напишу как функцию, так и вызывающего абонента, но вы никогда не можете быть уверены, что другие вызовут вашу процедуру правильно. –

+0

true ... Я думаю, что ck сделал хороший момент в отношении того, как его называют тысячи раз, поэтому накладные расходы на попытку/улов могут быть огромными. – kevchadders

1

Возможно, это связано с тем, что накладные расходы слишком велики - скалярная функция может быть вызвана в столбце как часть f выбора и так называться тысячами раз. Если бы были разумные накладные расходы, чтобы позволить попробовать/поймать, это бы ужасно сместило его.

+0

+1 Хороший вопрос о накладных расходах – kevchadders

+3

Да, ck, но мы могли бы сказать то же самое для многих других аспектов программирования (курсоры приходят на ум). Я бы сказал, что разработчик, который записывает эту функцию, может решить, будет ли она реализована, а возможное использование будет накладным и соответствующим кодом. –

Смежные вопросы