SQL Server 中对用户定义函数的需求是啥?
Posted
技术标签:
【中文标题】SQL Server 中对用户定义函数的需求是啥?【英文标题】:What is the need for user-defined functions in SQL Server?SQL Server 中对用户定义函数的需求是什么? 【发布时间】:2019-08-05 04:28:01 【问题描述】:SQL Server 中用户定义函数的确切需求是什么?
我们使用函数可以完成的所有事情都可以通过存储过程来完成,那么为什么要引入用户定义函数呢?
我知道存储过程和函数之间的区别,但它们都不能澄清我的问题,而且我找不到函数可以做而存储过程不能做的任何事情。
函数只是为了更好的可维护性和理解,还是我遗漏了什么?
【问题讨论】:
你可以在查询中使用函数in - 你不能用SP来做到这一点。 我自己会说可维护性 - 您可以在多个地方重复使用相同的查询,而无需重复代码。 “我们可以使用函数完成的所有事情都可以通过存储过程本身来完成”——这显然是不正确的。 【参考方案1】:我们使用函数可以完成的所有事情都可以通过存储过程本身来完成,
这是错误的。
无法重构或内联存储过程(例如VIEW
或表值函数 - 以及 SQL Server 2017 can now inline scalar functions too)。
数据库引擎无法证明存储过程“安全”(因为存储过程可以执行 DML/DDL 操作,而 UDF 只能执行只读操作)。
存储过程不能用于对标量值执行操作。
您可以提出这样的论点,即您可以在使用 UDF 的查询中执行的所有操作都可以在没有该 UDF 的情况下完成 - 这在技术上是正确的(因为存储过程 are Turing Complete),但这就像说我们不在 C# 中需要 for
、while
、try/catch
、using
或 async
,因为肯定 if
和 goto
对每个人都足够好!
代码质量、可维护性和运行时性能很重要 - 正确使用 UDF 不仅会产生美观的查询,而且由于内联、重组、表达式树修剪等,性能也会更好。
此外,在所有酷孩子都在使用实体框架的今天,谁在使用存储过程? :D
脚注
我想详细说明我的言论:
存储过程不能用于对标量值执行操作。
虽然存储过程确实有返回值和输出参数,但它们仍然与真正的 UDF 不同,因为存储过程返回值只能是 int
值(它们更接近于程序退出代码在 POSIX/Win32 中比实际返回值)和存储过程输出参数不能在另一个查询中使用,除非您使用 CURSOR
或动态 SQL(注入)进行丑陋的黑客攻击。
【讨论】:
从技术上讲,您可以使用输出通过存储过程对标量值执行操作(假设您的意思是输入一个变量并以不同的值输出它)。 @ZLK 但是,您不能在基于集合的操作中使用存储过程,这是 UDF 对它们的巨大优势。 @AlwaysLearning 是的,这在第一个要点中有所提及(因此,如果它是因为不能“内联”而提出的,那么这是一个多余的点)。 @ZLK 在基于集合的操作中使用函数(或存储过程)与它们可内联或可组合无关。 (除非您使用 SQL Server 2017 或更高版本,否则标量函数不会内联,并且标量函数在 SQL Server 2000 中运行良好 - 它们只是在计算上稍微昂贵一些。同样,假设 sprocs 可以如果 SQL Server 的产品设计团队决定添加对它的支持 - 可能使用一些复杂的语法,则可以在查询中使用(例如,在存储过程的结果表上到JOIN
)。【参考方案2】:
除了@Dai 已经提到的所有要点:我使用标量函数从相当大的 XML 列中“提取”某些位和片段作为原子值(例如 INT
等),并使用标量函数来定义一个计算列(基于那个 XML 列)。
这是您不能对存储过程做的另一件事 - 使用函数来定义计算列的值(或为“常规”列定义检查或默认约束)。
【讨论】:
以上是关于SQL Server 中对用户定义函数的需求是啥?的主要内容,如果未能解决你的问题,请参考以下文章