2010-01-05 79 views

回答

12

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行在功能中使用 副作用运算符'RAISERROR' 无效。

如果提出错误被认为是改变数据库状态,那么诱捕和处理一个错误也是可以的。我承认这不是一个解释。

但实际上,通常最好让调用者决定如何处理错误。假设你写这样一个函数:

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

你将如何处理应用程序对@y通过零的情况?如果您通过零例外来捕获除数,那么接下来要做什么?你可以从对调用者有意义的函数中返回什么样的值,记住你甚至可能不知道哪个应用程序正在调用你的函数?

您可能会想到返回NULL,但使用您的函数的应用程序开发人员会同意吗?他们的所有应用程序是否都将零差错划分为相同的影响或重要性?更不用说某些地方的NULL可以完全改变查询的结果,也许应用程序开发人员完全不需要。

如果你是唯一的开发者,也许这不是问题,但是随着更多的人迅速成为一个开发者。

+1

我想通过编写自己的UDF来重现TRY_CAST的行为: – 2014-11-12 16:02:37

1

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

+2

感谢您的回答,但是当您编写UDF时,通常会被其他人重复使用。 如果我写入函数和调用者,你的解决方案就可以工作,但你永远无法确定别人会以正确的方式调用你的过程。 – 2010-01-05 11:30:43

+0

是真的......我认为ck对它被称为数千次的潜力提出了一个很好的观点,所以try/catch的开销可能是巨大的。 – kevchadders 2010-01-05 13:55:31

1

也许是因为开销太大 - 标量函数可能作为select的一部分在列上调用,因此被称为数千次。如果有一个合理的开销来允许try/catch,它会使其变得非常糟糕。

+0

+1关于开销的好处 – kevchadders 2010-01-05 13:56:03

+3

是的,ck,但是我们可以说在编程的许多其他方面(游标都会想起来)是一样的。 我想说这取决于开发人员编写的函数来决定它的实现和可能的用法是开销,并相应地编码。 – 2010-01-05 14:52:36

相关问题