为什么SQL-Server UDF如此受限?

时间:2010-02-25 07:29:55

标签: sql sql-server user-defined-functions

来自create function的{​​{3}}:

User-defined functions cannot be used to perform actions that modify the database state.

我的问题很简单 - 为什么

是的,修改数据的UDF可能会产生潜在的不良副作用 是的,如果UDF被调用数千次,则会产生开销。

但这是设计和测试的全部要点 - 确保在部署之前解决这些问题。那么为什么数据库供应商坚持要对开发人员施加这些人为限制呢?语言构造的重点是什么,它基本上只能用作select语句的包装器?

这个问题的原因如下:我正在编写一个函数来返回某个唯一整数ID的GUID。如果已经为该ID分配了GUID,我只需将其返回;否则我想生成一个新的GUID,将其存储到表中,并返回新生成的GUID。 (是的,这听起来很啰嗦,可能很疯狂,但是当你把数据发送到另一家开发公司时,他们认为他们的设计是由上帝传下来的,而且无法改进,只是微笑点头并做他们要求的事情更容易)。

我知道我可以使用带有输出参数的存储过程来实现相同的结果,但是我必须声明一个新变量来保存sproc的结果。不仅如此,我还必须将简单的select转换为插入临时表的while循环,并在该循环的每次迭代中调用sproc。

3 个答案:

答案 0 :(得分:2)

通常最好将可用工具视为一种频谱,从视图,UDF到存储过程。在一端(视图),您有很多限制,但这意味着优化器实际上可以“透视”代码并做出明智的选择。在另一端(存储过程),你有很多灵活性,但由于你有这样的自由,你失去了一些能力(例如,因为你可以从存储过程中返回多个结果集,你失去了“撰写”的能力它作为更大查询的一部分。)

UDF处于中间位置 - 您可以在视图中执行更多操作(例如,多个语句),但是您没有存储过程那么多的灵活性。通过放弃这种自由,它允许输出作为更大查询的一部分组成。如果没有副作用,您可以保证,例如,应用UDF的行顺序无关紧要。如果您可能有副作用,优化程序可能必须提供排序保证。

答案 1 :(得分:0)

我认为我理解你的问题,但是从你的评论中得到这个:

  

我想做select my_udf(my_variable) from my_table之类的事情,其中​​my_udf选择或创建它返回的值

所以你想要select(可能)修改数据。你能不能自己看一下这句话,告诉我那句话完全没问题? - 我当然不能。

阅读您对实际需要做的描述:

  

我正在写一个函数来返回一个   某个唯一整数ID的GUID。   如果已分配GUID   那个ID我只是归还它;除此以外   我想生成一个新的GUID,商店   进入一张桌子,并返回   新生成的GUID。

     

我知道我可以使用存储的   输出参数的过程   实现相同的结果,但后来我   必须声明一个新的变量   保持sproc的结果。不只   那个,然后我必须转换我的简单   选择插入的while循环   进入临时表,然后打电话给   每次迭代的sproc   循环。

从最后一句话看起来你必须一次处理很多行,那么单个INSERT如何为那些尚未拥有它们的ID插入GUID,然后是一个SELECT 1}}返回(现在)存在的所有GUID?

答案 2 :(得分:0)

有时,如果您无法实现您提出的解决方案,则可能表明您的解决方案不是最佳解决方案。

使用这样的声明

INSERT INTO IntGuids(IntValue, GuidValue)
SELECT MyIntValues.IntValue, NEWID()
FROM MyIntValues
LEFT OUTER JOIN IntGuids ON MyIntValues.IntValue = IntGuids.IntValue
WHERE IntGuids.IntValue IS NULL

在1个语句中创建您需要的所有GUID。无需为每个值选择SELECT + INSERT。