函数和存储过程有什么区别?

use*_*365 3 sql-server stored-procedures functions

我听说 SQL Server 中函数和存储过程的区别在于函数不存储在数据库中,而存储过程存储在数据库中。

真的吗?如果不是,它们之间有什么区别?

另外,我知道存储过程只编译一次,然后直接执行。函数呢?

Aar*_*and 14

一个函数总是试图返回一些东西,并且有几个限制——例如,你不能有任何副作用,所以你不能发出 DML、调用存储过程、使用动态 SQL、调用NEWID()等。你也不能有错误GETDATE()在函数内部定义的处理、事务或非确定性函数(例如,在旧版本中,至少在 SQL Server 2000 中 - 尽管有解决方法)。

有几种类型的函数,主要是标量函数和表值函数。标量函数可以被内联调用,例如

CREATE FUNCTION dbo.PrettyDate(@d DATETIME)
RETURNS CHAR(10)
AS
BEGIN
    RETURN(SELECT CONVERT(CHAR(10), @d, 120));
END
GO

DECLARE @Date DATETIME = CURRENT_TIMESTAMP;
SELECT dbo.PrettyDate(@Date);
Run Code Online (Sandbox Code Playgroud)

结果:

----------
2012-03-14
Run Code Online (Sandbox Code Playgroud)

表值函数需要稍微不同地调用,因为它们本质上就像一个参数化视图。例如:

CREATE FUNCTION dbo.DatesInRange
(
  @StartDate DATETIME,
  @EndDate   DATETIME
)
RETURNS TABLE  
AS  
  RETURN (SELECT [date] = DATEADD(DAY, n-1, @StartDate)
    FROM (SELECT n = ROW_NUMBER() OVER (ORDER BY [object_id])
      FROM sys.objects) AS x
      WHERE n <= DATEDIFF(DAY, @StartDate, @EndDate) + 1
  );
GO

SELECT [date] 
  FROM dbo.DatesInRange('20120101', '20120105')
  ORDER BY [date];
Run Code Online (Sandbox Code Playgroud)

结果:

date
-----------------------
2012-01-01 00:00:00.000
2012-01-02 00:00:00.000
2012-01-03 00:00:00.000
2012-01-04 00:00:00.000
2012-01-05 00:00:00.000
Run Code Online (Sandbox Code Playgroud)

存储过程不一定返回数据,但可以返回多个结果集。可以用来影响数据(更新/插入/删除)等副作用,可以包含动态SQL,可以有事务,可以有错误处理,对非确定性函数没有限制,可以调用其他存储过程。

编辑

我不太确定您所说的“函数不存储在数据库中”是什么意思。当您创建存储过程或函数时,其定义肯定存储在目录视图中sys.sql_modules,并且在 中创建对模块的引用sys.objects。有存储过程(一个单独的目录视图sys.procedures),但没有为功能等效的观点-你仍然可以找到那些sys.objects与类型,如IFFNTF

我会回到问题的编译部分。