在SQL中什么时候应该使用函数而不是存储过程,反之亦然?每一个的目的是什么?
当前回答
函数是计算值,不能对SQL Server执行永久的环境更改(即不允许INSERT或UPDATE语句)。
如果函数返回标量值,则可以在SQL语句中使用它;如果函数返回结果集,则可以连接它。
从总结答案的评论中,有一点值得注意。感谢@Sean K Anderson:
函数遵循计算机科学的定义,即它们必须返回一个值,并且不能更改作为参数接收的数据 (论点)。函数不允许改变任何东西,必须 至少有一个参数,并且它们必须返回一个值。存储 Procs不需要有参数,可以改变数据库对象, 并且不需要返回值。
其他回答
当你想要计算并返回一个值以供其他SQL语句使用时,编写一个用户定义函数;当您想要编写存储过程时,您可以将一组可能很复杂的SQL语句分组。毕竟,这是两个非常不同的用例!
函数和存储过程有不同的用途。虽然这不是最好的类比,但函数可以从字面上视为任何编程语言中使用的任何其他函数,但存储的proc更像是单个程序或批处理脚本。
函数通常有一个输出和可选的输入。输出可以作为另一个函数的输入(SQL Server内置的,如DATEDIFF, LEN等)或作为SQL查询的谓词-例如,SELECT a, b, dbo.MyFunction(c) FROM表或SELECT a, b, c FROM表WHERE a = dbo.MyFunc(c)。
Stored proc用于将SQL查询绑定到事务中,并与外部世界进行交互。框架,如ADO。NET等不能直接调用函数,但可以直接调用存储过程。
函数确实有一个隐患:它们可能被误用并导致相当严重的性能问题:考虑以下查询:
SELECT * FROM dbo.MyTable WHERE col1 = dbo.MyFunction(col2)
其中MyFunction声明为:
CREATE FUNCTION MyFunction (@someValue INTEGER) RETURNS INTEGER
AS
BEGIN
DECLARE @retval INTEGER
SELECT localValue
FROM dbo.localToNationalMapTable
WHERE nationalValue = @someValue
RETURN @retval
END
这里发生的事情是,MyFunction函数被MyTable表中的每一行调用。如果MyTable有1000行,那么就有另外1000个针对数据库的特别查询。类似地,如果函数在列规范中指定时被调用,则该函数将对SELECT返回的每一行被调用。
所以写函数的时候一定要小心。如果从函数中的表执行SELECT操作,则需要问问自己,在父进程中使用JOIN或其他SQL构造(如CASE…当……其他的……结束)。
要决定何时使用以下几点可能会有所帮助-
存储过程不能返回表变量,而函数可以这样做。 您可以使用存储过程来更改服务器环境参数,而使用函数则不能。
干杯
一般来说,使用存储过程的性能更好。 例如,在以前版本的SQL Server中,如果你将函数置于JOIN条件下,基数估计为1 (SQL 2012之前)和100 (SQL 2012之后和SQL 2017之前),引擎可能会生成一个糟糕的执行计划。
此外,如果你把它放在WHERE子句中,SQL引擎可能会生成一个糟糕的执行计划。
在SQL 2017中,微软引入了称为交错执行的功能,以产生更准确的估计,但存储过程仍然是最佳解决方案。
要了解更多细节,请参阅以下Joe Sack的文章 https://techcommunity.microsoft.com/t5/sql-server/introducing-interleaved-execution-for-multi-statement-table/ba-p/385417
存储过程用作脚本。它们为您运行一系列命令,您可以安排它们在特定时间运行。通常运行多个DML语句,如INSERT, UPDATE, DELETE等,甚至是SELECT。
函数用作方法。你给它传递一些东西,它会返回一个结果。应该是小而快速的-在飞行中。通常在SELECT语句中使用。
推荐文章
- 如何在Ruby On Rails中使用NuoDB手动执行SQL命令
- 查询JSON类型内的数组元素
- 确定记录是否存在的最快方法
- 获得PostgreSQL数据库中当前连接数的正确查询
- 在SQL选择语句Order By 1的目的是什么?
- 从现有模式生成表关系图(SQL Server)
- 我如何循环通过一组记录在SQL Server?
- 数据库和模式的区别
- 如何在SQL Server中一次更改多个列
- 如何从命令行通过mysql运行一个查询?
- 外键约束可能导致循环或多条级联路径?
- 使用LIMIT/OFFSET运行查询,还可以获得总行数
- 当恢复sql时,psql无效命令\N
- 货币应该使用哪种数据类型?
- 如何选择每一行的列值不是独特的