在SQL中什么时候应该使用函数而不是存储过程,反之亦然?每一个的目的是什么?
当前回答
存储过程用作脚本。它们为您运行一系列命令,您可以安排它们在特定时间运行。通常运行多个DML语句,如INSERT, UPDATE, DELETE等,甚至是SELECT。
函数用作方法。你给它传递一些东西,它会返回一个结果。应该是小而快速的-在飞行中。通常在SELECT语句中使用。
其他回答
函数和存储过程有不同的用途。虽然这不是最好的类比,但函数可以从字面上视为任何编程语言中使用的任何其他函数,但存储的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…当……其他的……结束)。
下面是一个总结差异的表格:
Stored Procedure | Function | |
---|---|---|
Returns | Zero or more values | A single value (which may be a scalar or a table) |
Can use transaction? | Yes | No |
Can output to parameters? | Yes | No |
Can call each other? | Can call a function | Cannot call a stored procedure |
Usable in SELECT, WHERE and HAVING statements? | No | Yes |
Supports exception handling (via try/catch)? | Yes | No |
一般来说,使用存储过程的性能更好。 例如,在以前版本的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
从返回单个值的函数开始。这样做的好处是,您可以将经常使用的代码放入函数中,并将它们作为结果集中的列返回。
然后,可以使用一个函数来表示参数化的城市列表。getcitiesin ("NY")返回一个可以用作连接的表。
这是一种组织代码的方式。知道什么时候是可重用的,什么时候是浪费时间,只有通过试验、错误和经验才能获得。
此外,函数在SQL Server中也是一个好主意。它们速度更快,功能也相当强大。内联和直接选择。注意不要过度使用。
用户定义函数是sql server程序员可用的重要工具。您可以像这样在SQL语句中内联使用它
SELECT a, lookupValue(b), c FROM customers
其中lookupValue将是UDF。这种功能在使用存储过程时是不可能实现的。同时,您不能在UDF中做某些事情。这里要记住的基本事情是UDF的:
不能产生永久的变化 无法更改数据
存储过程可以做这些事情。
对我来说,UDF的内联使用是UDF最重要的使用。
推荐文章
- 如何在Ruby On Rails中使用NuoDB手动执行SQL命令
- 查询JSON类型内的数组元素
- 确定记录是否存在的最快方法
- 获得PostgreSQL数据库中当前连接数的正确查询
- 在SQL选择语句Order By 1的目的是什么?
- 从现有模式生成表关系图(SQL Server)
- 我如何循环通过一组记录在SQL Server?
- 数据库和模式的区别
- 如何在SQL Server中一次更改多个列
- 如何从命令行通过mysql运行一个查询?
- 外键约束可能导致循环或多条级联路径?
- 使用LIMIT/OFFSET运行查询,还可以获得总行数
- 当恢复sql时,psql无效命令\N
- 货币应该使用哪种数据类型?
- 如何选择每一行的列值不是独特的