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


当前回答

函数是计算值,不能对SQL Server执行永久的环境更改(即不允许INSERT或UPDATE语句)。

如果函数返回标量值,则可以在SQL语句中使用它;如果函数返回结果集,则可以连接它。

从总结答案的评论中,有一点值得注意。感谢@Sean K Anderson:

函数遵循计算机科学的定义,即它们必须返回一个值,并且不能更改作为参数接收的数据 (论点)。函数不允许改变任何东西,必须 至少有一个参数,并且它们必须返回一个值。存储 Procs不需要有参数,可以改变数据库对象, 并且不需要返回值。

其他回答

存储过程:

就像SQL Server中的一个微型程序。 可以像选择语句一样简单,也可以像长语句一样复杂 从多个服务器中添加、删除、更新和/或读取数据的脚本 数据库中的表。 (可以实现循环和游标,两者都允许您使用 较小的结果或对数据的逐行操作。) 应该使用EXEC或EXECUTE语句调用。 返回表变量,但不能使用OUT参数。 支持事务。

功能:

Can not be used to update, delete, or add records to the database. Simply returns a single value or a table value. Can only be used to select records. However, it can be called very easily from within standard SQL, such as: SELECT dbo.functionname('Parameter1') or SELECT Name, dbo.Functionname('Parameter1') FROM sysObjects For simple reusable select operations, functions can simplify code. Just be wary of using JOIN clauses in your functions. If your function has a JOIN clause and you call it from another select statement that returns multiple results, that function call will JOIN those tables together for each line returned in the result set. So though they can be helpful in simplifying some logic, they can also be a performance bottleneck if they're not used properly. Returns the values using OUT parameter. Does not support transactions.

我知道这是一个非常老的问题,但是我在任何答案中都没有看到一个关键的方面:内联到查询计划中。

函数可以是…

标量: 创建函数…返回scalar_type AS BEGIN…结束 Multi-statement表值: 创建函数…返回@r表(…)开始…结束 内联表值: 创建函数…返回表作为return select…

第三种(内联表值)被查询优化器本质上视为(参数化)视图,这意味着从查询中引用函数类似于复制粘贴函数的SQL主体(而不是实际的复制粘贴),导致以下好处:

查询计划器可以优化内联函数的执行,就像它会优化任何其他子查询一样(例如,消除未使用的列,下推谓词,选择不同的JOIN策略等)。 组合几个内联函数并不需要在将第一个函数的结果提供给下一个函数之前实现它。

上述方法可能会带来潜在的显著性能节省,特别是在组合多个级别的功能时。


注意:看起来SQL Server 2019也将引入某种形式的标量函数内联。

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

It is mandatory for Function to return a value while it is not for stored procedure. Select statements only accepted in UDF while DML statements not required. Stored procedure accepts any statements as well as DML statements. UDF only allows inputs and not outputs. Stored procedure allows for both inputs and outputs. Catch blocks cannot be used in UDF but can be used in stored procedure. No transactions allowed in functions in UDF but in stored procedure they are allowed. Only table variables can be used in UDF and not temporary tables. Stored procedure allows for both table variables and temporary tables. UDF does not allow stored procedures to be called from functions while stored procedures allow calling of functions. UDF is used in join clause while stored procedures cannot be used in join clause. Stored procedure will always allow for return to zero. UDF, on the contrary, has values that must come - back to a predetermined point.

存储过程用作脚本。它们为您运行一系列命令,您可以安排它们在特定时间运行。通常运行多个DML语句,如INSERT, UPDATE, DELETE等,甚至是SELECT。

函数用作方法。你给它传递一些东西,它会返回一个结果。应该是小而快速的-在飞行中。通常在SELECT语句中使用。