在SQL中什么时候应该使用函数而不是存储过程,反之亦然?每一个的目的是什么?
当前回答
用户定义函数是sql server程序员可用的重要工具。您可以像这样在SQL语句中内联使用它
SELECT a, lookupValue(b), c FROM customers
其中lookupValue将是UDF。这种功能在使用存储过程时是不可能实现的。同时,您不能在UDF中做某些事情。这里要记住的基本事情是UDF的:
不能产生永久的变化 无法更改数据
存储过程可以做这些事情。
对我来说,UDF的内联使用是UDF最重要的使用。
其他回答
函数和存储过程有不同的用途。虽然这不是最好的类比,但函数可以从字面上视为任何编程语言中使用的任何其他函数,但存储的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函数,比如游标,是你最后的武器!它们确实存在性能问题,因此应该尽可能避免使用表值函数。谈论性能就是谈论一个有超过1,000,000条记录的表托管在一个中产阶级硬件的服务器上;否则,您不需要担心函数对性能的影响。
永远不要使用函数将结果集返回给外部代码(如ADO.Net) 尽可能使用视图/存储procs组合。您可以使用DTA(数据库调优顾问)给您的建议(比如索引视图和统计数据)来解决未来的增长性能问题——有时!
如需进一步参考,请参阅:http://databases.aspfaq.com/database/should-i-use-a-view-a-stored-procedure-or-a-user-defined-function.html
要决定何时使用以下几点可能会有所帮助-
存储过程不能返回表变量,而函数可以这样做。 您可以使用存储过程来更改服务器环境参数,而使用函数则不能。
干杯
这里有一个更喜欢函数而不是存储过程的实际原因。如果有一个存储过程需要另一个存储过程的结果,则必须使用insert-exec语句。这意味着您必须创建一个临时表并使用exec语句将存储过程的结果插入到临时表中。它是混乱的。这样做的一个问题是insert-execs不能嵌套。
如果您使用调用其他存储过程的存储过程,可能会遇到这种情况。如果嵌套存储过程只是返回一个数据集,则可以将其替换为表值函数,这样就不会再出现此错误。
(这是我们应该将业务逻辑排除在数据库之外的另一个原因)
推荐文章
- 如何在Ruby On Rails中使用NuoDB手动执行SQL命令
- 查询JSON类型内的数组元素
- 确定记录是否存在的最快方法
- 获得PostgreSQL数据库中当前连接数的正确查询
- 在SQL选择语句Order By 1的目的是什么?
- 从现有模式生成表关系图(SQL Server)
- 我如何循环通过一组记录在SQL Server?
- 数据库和模式的区别
- 如何在SQL Server中一次更改多个列
- 如何从命令行通过mysql运行一个查询?
- 外键约束可能导致循环或多条级联路径?
- 使用LIMIT/OFFSET运行查询,还可以获得总行数
- 当恢复sql时,psql无效命令\N
- 货币应该使用哪种数据类型?
- 如何选择每一行的列值不是独特的