在SQL中什么时候应该使用函数而不是存储过程,反之亦然?每一个的目的是什么?


当前回答

函数可以在选择语句中使用,而过程则不能。 存储过程同时接受输入和输出参数,而函数只接受输入参数。 函数不能返回text, ntext, image和时间戳类型的值,而过程可以。 函数可以在创建表中作为用户定义的数据类型使用,但过程不能。

***例如:-create table <tablename>(name varchar(10),salary getsal(name))

这里getsal是一个用户定义的函数,它返回一个工资类型,当创建表时,没有存储空间分配给工资类型,getsal函数也不执行,但当我们从这个表中获取一些值时,getsal函数get被执行,返回 类型作为结果集返回。

其他回答

函数和存储过程有不同的用途。虽然这不是最好的类比,但函数可以从字面上视为任何编程语言中使用的任何其他函数,但存储的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

从返回单个值的函数开始。这样做的好处是,您可以将经常使用的代码放入函数中,并将它们作为结果集中的列返回。

然后,可以使用一个函数来表示参数化的城市列表。getcitiesin ("NY")返回一个可以用作连接的表。

这是一种组织代码的方式。知道什么时候是可重用的,什么时候是浪费时间,只有通过试验、错误和经验才能获得。

此外,函数在SQL Server中也是一个好主意。它们速度更快,功能也相当强大。内联和直接选择。注意不要过度使用。

这里有一个更喜欢函数而不是存储过程的实际原因。如果有一个存储过程需要另一个存储过程的结果,则必须使用insert-exec语句。这意味着您必须创建一个临时表并使用exec语句将存储过程的结果插入到临时表中。它是混乱的。这样做的一个问题是insert-execs不能嵌套。

如果您使用调用其他存储过程的存储过程,可能会遇到这种情况。如果嵌套存储过程只是返回一个数据集,则可以将其替换为表值函数,这样就不会再出现此错误。

(这是我们应该将业务逻辑排除在数据库之外的另一个原因)

下面是一个总结差异的表格:

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