【问题标题】:Why is TRY-CATCH block not allowed inside UDFs?为什么 UDF 中不允许 TRY-CATCH 块?
【发布时间】:2011-01-01 14:30:18
【问题描述】:

为什么 SQL Server 不支持 UDF 中的 TRY-CATCH 块?

如果我们谈论的是主要用于计算和对话的标量 UDF,那么这个块应该被大量使用,但我们没有。

另外,您对此使用了哪些解决方法?

【问题讨论】:

    标签: tsql user-defined-functions


    【解决方案1】:

    使用 SQLServer 2012,您可以尝试exec sp_your_procedure_with_try_catch,它对我有用。

    其实我的几个触发器都有一键SP的逻辑。我不知道 UDF 中不允许 try-catch,直到我尝试在没有 SP 的情况下重写其中一些。

    【讨论】:

    • 问题是关于函数,而不是过程。
    【解决方案2】:

    MSSQL 中的UDF 不允许有副作用,BOL 将其定义为“改变数据库状态”。这是一个相当模糊的描述,但 MSSQL 显然认为错误会改变数据库状态 - 此 UDF 无法编译:

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

    错误信息是:

    消息 443,级别 16,状态 14,程序 foo,第 5 行无效使用 a 副作用运算符“RAISERROR” 在函数中。

    如果认为引发错误会改变数据库状态,那么捕获和处理可能也是如此。我承认,这没什么好解释的。

    不过,实际上,最好还是让调用者决定如何处理错误。假设你写了一个这样的函数:

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

    您将如何处理应用程序为@y 传递零的情况?如果你捕捉到除以零异常,你接下来要做什么?你可以从对调用者有意义的函数返回什么值,记住你可能甚至不知道哪个应用程序正在调用你的函数?

    您可能会考虑返回 NULL,但使用您的函数的应用程序开发人员会同意吗?他们所有的应用程序是否都认为除以零错误具有相同的影响或重要性?更不用说某些地方的 NULL 可以完全改变查询的结果,可能是应用程序开发人员根本不想要的方式。

    如果您是唯一的开发人员,也许这不是问题,但随着更多的人,它很快就会成为一个问题。

    【讨论】:

    • 我想通过编写自己的 UDF 来重现 TRY_CAST 的行为:
    【解决方案3】:

    可能是因为开销太大 - 标量函数可以作为选择的一部分在列上调用,因此被调用数千次。如果允许 try/catch 有合理的开销,它会大大减慢它。

    【讨论】:

    • 是的,ck,但我们可以对编程的许多其他方面说同样的话(想到光标)。我想说由编写函数的开发人员决定它的实现和可能的使用是否会产生开销,并相应地编写代码。
    【解决方案4】:

    作为一种解决方法,我会在存储过程中从 TRY/CATCH 调用 UDF。

    【讨论】:

    • 感谢您的回答,但是当您编写 UDF 时,它通常会被其他人重用。如果我同时编写函数和调用者,您的解决方案就有效,但您永远无法确定其他人会以正确的方式调用您的过程。
    • true...我认为 ck 对它被调用数千次的潜力提出了一个很好的观点,因此 try/catch 的开销可能是巨大的。
    猜你喜欢
    • 2011-07-25
    • 2012-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多