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# 中需要 forwhiletry/catchusingasync,因为肯定 ifgoto 对每个人都足够好!

代码质量、可维护性和运行时性能很重要 - 正确使用 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 中对用户定义函数的需求是啥?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server中对存储过程的理解

在这种情况下,在 SQL Server 中对三个 nchar 列进行索引的最有效方法是啥?

Sql Server 2012 中序列的真正需求是啥?

SQL Server中的开窗函数是啥?

sql server中dbcheck 数据库是啥命令

sql server中对字段使用正则表达式替换???