Обработка ошибок в скалярной функции T-SQL - PullRequest
5 голосов
/ 27 мая 2010

Этот вопрос может легко занять несколько путей, поэтому сначала я выберу более конкретный путь. Работая с SQL Server 2005, я пытаюсь создать скалярную функцию, которая действует как TryCast от varchar до int. Я сталкиваюсь с проблемой, когда добавляю блок TRY в функцию;

CREATE FUNCTION u_TryCastInt
(
   @Value as VARCHAR(MAX)
)
RETURNS Int
AS
BEGIN
   DECLARE @Output AS Int

   BEGIN TRY
      SET @Output = CONVERT(Int, @Value)
   END TRY
   BEGIN CATCH
      SET @Output = 0
   END CATCH

   RETURN @Output
END

Оказывается, что в этом утверждении есть все виды неправильных вещей, включая «Недопустимое использование побочного или зависящего от времени оператора в« НАЧАТЬ ИДЕТ »внутри функции» и «Недопустимое использование побочного или зависящего от времени оператора в «КОНЕЦ ПОПРОБУЙТЕ» в функции ». Кажется, я не могу найти никаких примеров использования операторов try внутри скалярной функции, что заставило меня задуматься о том, возможна ли обработка ошибок в функции?

Целью здесь является создание надежной версии функций Convert или Cast, чтобы оператор SELECT мог переносить ошибки преобразования с места. Например, возьмите следующее:

    CREATE TABLE tblTest
    (
        f1 VARCHAR(50)
    )
    GO

    INSERT INTO tblTest(f1) VALUES('1')
    INSERT INTO tblTest(f1) VALUES('2')
    INSERT INTO tblTest(f1) VALUES('3')
    INSERT INTO tblTest(f1) VALUES('f')
    INSERT INTO tblTest(f1) VALUES('5')
    INSERT INTO tblTest(f1) VALUES('1.1')

    SELECT CONVERT(int,f1) AS f1_num FROM tblTest

    DROP TABLE tblTest

Он никогда не достигнет точки сброса таблицы, потому что выполнение зависает при попытке преобразовать 'f' в целое число. Я хочу быть в состоянии сделать что-то вроде этого;

SELECT u_TryCastInt(f1) AS f1_num FROM tblTest

fi_num
__________
1
2
3
0
5
0

Есть мысли по этому поводу? Есть ли что-нибудь, что может с этим справиться? Кроме того, я хотел бы попытаться расширить диалог для поддержки SQL Server 2000, поскольку блоки Try в этом сценарии недоступны.

Ответы [ 3 ]

5 голосов
/ 27 мая 2010

Проверьте, можете ли вы сначала преобразовать в int, проверьте функцию IsInteger здесь: IsNumeric, IsInt, IsNumber Это будет работать на 2000 и выше

2 голосов
/ 01 марта 2011

И, в общем, отвечаю: нет, вы не можете использовать логику try-catch в функции. Я могу понять почему - или, по крайней мере, явно предпочтительнее избегать этого, учитывая огромное снижение производительности, которое будет с этим связано.

Тем не менее, я думаю, что странно, что нельзя также выдавать ошибку в функции ... это то, что встроенные функции уже делают. Я полагаю, что нужно получить, возвращая NULL.

0 голосов
/ 20 мая 2014

Конструкция TRY… CATCH не может использоваться в пользовательской функции в SQL 2012!

Смотрите это: http://msdn.microsoft.com/en-us/library/ms175976.aspx

Когда я пытаюсь использовать этот скрипт:

CREATE FUNCTION u_TryCastInt
(
   @Value as VARCHAR(MAX)
)
RETURNS Int
AS
BEGIN
   DECLARE @Output AS Int

   BEGIN TRY
      SET @Output = CONVERT(Int, @Value)
   END TRY
   BEGIN CATCH
      SET @Output = 0
   END CATCH

   RETURN @Output
END

Я получил ошибку:

Сообщение 443, Уровень 16, Состояние 14, Процедура u_TryCastInt, Строка 10
Неправильное использование побочного эффекта оператора «BEGIN TRY» внутри функции.
Сообщение 443, уровень 16, состояние 14, процедура u_TryCastInt, строка 12
Неправильное использование побочного эффекта оператора 'END TRY' внутри функции.
Сообщение 443, уровень 16, состояние 14, процедура u_TryCastInt, строка 13
Неправильное использование побочного эффекта оператора «BEGIN CATCH» внутри функции.
Сообщение 443, уровень 16, состояние 14, процедура u_TryCastInt, строка 15
Неправильное использование побочного эффекта оператора «END CATCH» внутри функции.

...