为什么SQL Server UDF如此有限?

为什么SQL Server UDF如此有限?,sql,sql-server,user-defined-functions,Sql,Sql Server,User Defined Functions,从for创建函数中: 用户定义的函数不能用于执行修改数据库状态的操作。 我的问题很简单-为什么 是的,修改数据的UDF可能有潜在的不必要的副作用。 是的,如果一个UDF被调用了数千次,则会涉及开销 但这就是设计和测试的全部要点——确保在部署之前解决这些问题。那么,为什么数据库供应商坚持对开发人员施加这些人为的限制呢?本质上只能用作select语句的包装器的语言构造有什么意义 这个问题的原因如下:我正在编写一个函数来返回某个唯一整数ID的GUID。如果已经为该ID分配了GUID,我只需返回它;否则

从for
创建函数中

用户定义的函数不能用于执行修改数据库状态的操作。

我的问题很简单-为什么

是的,修改数据的UDF可能有潜在的不必要的副作用。
是的,如果一个UDF被调用了数千次,则会涉及开销

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

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


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

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


UDF处于中间位置—您可以做的比在视图中做的更多(例如,多个语句),但您没有存储过程那么大的灵活性。通过放弃这种自由,它允许将输出作为更大查询的一部分进行组合。例如,通过没有副作用,您可以保证UDF应用于哪个行顺序并不重要。如果您可能有副作用,优化器可能必须提供订购保证。

我理解您的问题,我想,但从您的评论中可以看出:

我想从my_表中选择my_udf(my_变量),其中,
my_udf
选择或创建它返回的值

因此,您需要一个
选择
,它(可能)修改数据。你能单独看一下这个句子,告诉我它读起来很好吗我当然不能

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

我正在编写一个函数来返回 特定唯一整数ID的GUID。 如果已为分配GUID 我只是把它还给你;否则 我想生成一个新的GUID存储 将其放入表中,并返回 新生成的GUID

我知道我可以使用存储的 将输出参数设置为 达到同样的结果,但我 必须声明一个新变量才能 保留存储过程的结果。不仅 然后,我必须转换我的简单 选择插入的while循环 进入临时表,并调用 每次迭代的存储过程 循环


从最后一句话来看,您似乎必须一次处理多行,因此,如果一个
INSERT
,为那些还没有GUID的ID插入GUID,然后一个
SELECT
,返回(现在)存在的所有GUID,怎么样?

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

使用这样的语句

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。无需为每个值选择+插入。

如果需要修改数据库状态,为什么不直接使用存储过程呢??UDF用于快速计算、查找或返回单个值——这就是它们的全部用途。他们做得很好,因为我想做一些类似于从my_表中选择my_udf(my_变量)的事情,其中,
my_udf
选择或创建它返回的值(如我在文章中解释的)。使用存储过程来获得相同的结果会使代码大10倍左右。