SQL Server中的函数与存储过程

Tar*_*rik 801 sql t-sql sql-server stored-procedures sql-function

我一直在学习函数和存储过程很长一段时间,但我不知道为什么以及何时应该使用函数或存储过程.他们看起来和我一样,也许是因为我对此有点新手.

有人可以告诉我为什么吗?

MyI*_*hin 691

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

如果函数返回标量值,则可以在SQL语句中内联使用该函数;如果返回结果集,则可以将其连接在一起.

值得注意的一点是评论,总结了答案.感谢@Sean K Anderson:

函数遵循计算机技术定义,因为它们必须返回一个值,并且不能改变它们作为参数(参数)接收的数据.函数不允许更改任何内容,必须至少有一个参数,并且它们必须返回一个值.存储过程不必具有参数,可以更改数据库对象,也不必返回值.

  • 函数遵循计算机技术定义,因为它们必须返回一个值,并且不能改变它们作为参数(参数)接收的数据.函数不允许更改任何内容,必须至少有一个参数,并且它们必须返回一个值.存储过程不必具有参数,可以更改数据库对象,也不必返回值. (164认同)
  • @SeanKAnderson函数"必须至少有一个参数"是不正确的. (37认同)
  • 实际上,您可以在函数中使用INSERT,UPDATE和DELETE语句来修改本地表变量. (21认同)
  • 基本上不允许DML? (13认同)
  • @Ani - 您可以在函数中实例化和修改任意数量的局部变量,但是您无法修改函数范围之外的任何内容. (12认同)
  • 注意:滥用内联函数会严重降低查询速度 (3认同)

Bha*_*tel 597

SP和UDF之间的区别如下:

+---------------------------------+----------------------------------------+
| Stored Procedure (SP)           | Function (UDF - User Defined           |
|                                 | Function)                              |
+---------------------------------+----------------------------------------+
| SP can return zero , single or  | Function must return a single value    |
| multiple values.                | (which may be a scalar or a table).    |
+---------------------------------+----------------------------------------+
| We can use transaction in SP.   | We can't use transaction in UDF.       |
+---------------------------------+----------------------------------------+
| SP can have input/output        | Only input parameter.                  |
| parameter.                      |                                        |
+---------------------------------+----------------------------------------+
| We can call function from SP.   | We can't call SP from function.        |
+---------------------------------+----------------------------------------+
| We can't use SP in SELECT/      | We can use UDF in SELECT/ WHERE/       |
| WHERE/ HAVING statement.        | HAVING statement.                      |
+---------------------------------+----------------------------------------+
| We can use exception handling   | We can't use Try-Catch block in UDF.   |
| using Try-Catch block in SP.    |                                        |
+---------------------------------+----------------------------------------+
Run Code Online (Sandbox Code Playgroud)

  • 函数必须返回一个值或一组. (19认同)
  • 这是3年之后,但应该是最重要的,因为它既可读又广泛. (7认同)
  • SP 可以同时使用临时表和表变量,而 UDF 可以仅使用表变量。表变量反过来可能不使用索引。与 SP 不同,UDF 可以在 CROSS APPLY 中调用 (2认同)

Chr*_*s J 187

函数和存储过程用于单独的目的.虽然它不是最好的类比,但函数可以像任何编程语言中使用的任何其他函数一样被视为字体,但存储过程更像是单个程序或批处理脚本.

功能通常具有输出和可选输入.然后输出可以用作另一个函数(内置的SQL Server,如DATEDIFF,LEN等)的输入,或者作为SQL查询的谓词 - 例如,SELECT a, b, dbo.MyFunction(c) FROM tableSELECT a, b, c FROM table WHERE a = dbo.MyFunc(c).

存储过程用于在事务中将SQL查询绑定在一起,并与外部世界进行交互.ADO.NET等框架不能直接调用函数,但可以直接调用存储过程.

函数确实有一个隐藏的危险:它们可能被滥用并导致相当令人讨厌的性能问题:考虑这个查询:

SELECT * FROM dbo.MyTable WHERE col1 = dbo.MyFunction(col2)
Run Code Online (Sandbox Code Playgroud)

MyFunction声明为:

CREATE FUNCTION MyFunction (@someValue INTEGER) RETURNS INTEGER
AS
BEGIN
   DECLARE @retval INTEGER

   SELECT localValue 
      FROM dbo.localToNationalMapTable
      WHERE nationalValue = @someValue

   RETURN @retval
END
Run Code Online (Sandbox Code Playgroud)

这里发生的是为MyTable表中的每一行调用函数MyFunction.如果MyTable有1000行,那么这是针对数据库的另外1000个临时查询.类似地,如果在列规范中指定函数时调用该函数,则将为SELECT返回的每一行调用该函数.

所以你需要小心编写函数.如果从函数中的表中执行SELECT,则需要问自己,在父存储过程或其他SQL构造中使用JOIN是否可以更好地执行SELECT(例如CASE ... WHEN ... ELSE ...结束).

  • 你必须通过一些SELECT语句调用一个函数 - 一个函数本身不能作为一个独立的代码段调用 - 它必须作为一些较大的SQL语句的一部分被调用,即使那个SQL语句不再是比'SELECT*from dbo.MyTableValuedFunction()`.另一方面,通过将`SqlCommand.CommandType`设置为`CommandType.StoredProcedure`,可以直接使用ADO.NET调用Sprocs. (24认同)
  • 能否详细说明"ADO.NET等框架不能直接调用函数"?我已经使用ADO.NET数据提供程序执行了函数,没有任何问题. (2认同)

Kum*_*PMP 58

存储过程和用户​​定义函数之间的差异:

  • 存储过程不能在Select语句中使用.
  • 存储过程支持延迟名称解析.
  • 存储过程通常用于执行业务逻辑.
  • 存储过程可以返回任何数据类型.
  • 存储过程可以接受比用户定义的函数更多的输入参数.存储过程最多可包含21,000个输入参数.
  • 存储过程可以执行动态SQL.
  • 存储过程支持错误处理.
  • 可以在存储过程中使用非确定性函数.

  • 用户定义的函数可以在Select语句中使用.
  • 用户定义的函数不支持延迟名称解析.
  • 用户定义的函数通常用于计算.
  • 用户定义的函数应返回一个值.
  • 用户定义的函数无法返回图像.
  • 用户定义的函数接受的输入参数数量少于存储过程.UDF最多可包含1,023个输入参数.
  • 临时表不能用于用户定义的函数.
  • 用户定义的函数无法执行动态SQL.
  • 用户定义的函数不支持错误处理. UDF中不允许使用RAISEERROROR @@ERROR.
  • UDF中不能使用非确定性函数.例如,GETDATE()不能在UDF中使用.

  • 本博客自2014年10月8日起编写,此答案自2013年5月2日@Tom撰写 (6认同)
  • 在下面引用@curiousBoy。另一个未经认可的答案(@Ankit)(<-- 看看我是怎么做的?;)):“您应该提供源参考。这是来自(https://blogs.msdn.microsoft.com/pradeepsvs /2014/10/08/difference-between-a-stored-procedure-and-function/)。请尊重他人所做的工作!” (2认同)

Ale*_*lli 56

当您想要计算并返回一个值以便在其他SQL语句中使用时,编写用户定义的函数; 在需要时编写存储过程,而不是将一组可能复杂的SQL语句分组.毕竟,这是两个截然不同的用例!

  • 有不同类型的用户定义函数.标量只返回值; 其他类型的retrun结果集. (17认同)

Aak*_*ngh 34

              STORE PROCEDURE                 FUNCTION (USER DEFINED FUNCTION)    
 * Procedure can return 0, single or   | * Function can return only single value   
   multiple values.                    |
                                       |
 * Procedure can have input, output    | * Function  can have only input 
   parameters.                         |   parameters.         
                                       |
 * Procedure cannot be called from     | * Functions can be called from 
   function.                           |   procedure.
                                       |
 * Procedure allows select as well as  | * Function allows only select statement 
   DML statement in it.                |   in it.
                                       |
 * Exception can be handled by         | * Try-catch block cannot be used in a 
   try-catch block in a procedure.     |   function.
                                       |
 * We can go for transaction management| * We can't go for transaction 
   in procedure.                       |   management in function.
                                       |
 * Procedure cannot be utilized in a   | * Function can be embedded in a select 
   select statement                    |   statement.
                                       |
 * Procedure can affect the state      | * Function can not affect the state 
   of database means it can perform    |   of database means it can not    
   CRUD operation on database.         |   perform CRUD operation on 
                                       |   database. 
                                       |
 * Procedure can use temporary tables. | * Function can not use 
                                       |   temporary tables. 
                                       |
 * Procedure can alter the server      | * Function can not alter the  
   environment parameters.             |   environment parameters.
                                       |   
 * Procedure can use when we want      | * Function can use when we want
   instead is to group a possibly-     |   to compute and return a value
   complex set of SQL statements.      |   for use in other SQL 
                                       |   statements.
Run Code Online (Sandbox Code Playgroud)


小智 22

基本差异

函数必须返回一个值,但在存储过程中它是可选的(过程可以返回零或n个值).

函数只能有输入参数,而程序可以有输入/输出参数.

函数需要一个输入参数,它是必需的,但存储过程可能需要o到n个输入参数.

可以从Procedure调用函数,但不能从Function调用过程.

预付差异

Procedure允许SELECT和DML(INSERT/UPDATE/DELETE)语句,而Function只允许SELECT语句.

程序不能在SELECT语句中使用,而Function可以嵌入SELECT语句中.

存储过程不能在WHERE/HAVING/SELECT部分​​的任何地方的SQL语句中使用,而Function可以.

返回表的函数可以视为另一个行集.这可以在JOIN中与其他表一起使用.

内联函数可以作为带参数的视图,可以在JOIN和其他Rowset操作中使用.

异常可以通过过程中的try-catch块来处理,而try-catch块不能在Function中使用.

我们可以在程序中进行事务管理,而我们不能进入功能.

资源

  • 您应该已经给出了源参考.这来自http://www.dotnet-tricks.com/Tutorial/sqlserver/7EDL150912-Difference-between-Stored-Procedure-and-Function-in-SQL-Server.html.请尊重他人的工作! (24认同)
  • 这不是不提供源参考的理由.你可以在最后提到它! (15认同)
  • 关于。“函数必须返回一个值,但在存储过程中它是可选的......”:我要澄清的是:“函数**必须**返回一个且只有一个值(必须通过`Returns`关键字完成并且必须是标量或表类型),但存储过程可以**可选地**返回:a) 1 个通过 `Return` 语句的 `Int` 类型结果代码和/或 b) 1+ 个参数(包括 `Cursor` 类型)通过 `Output` 关键字和/或 c) 1+ 行集通过 `Select` 语句。如果只返回 1 个行集,它可以用作“插入”语句的“execute_statement”参数。 (2认同)

Ope*_*rce 19

用户定义函数是sql server程序员可用的重要工具.您可以在SQL语句中内联使用它

SELECT a, lookupValue(b), c FROM customers 
Run Code Online (Sandbox Code Playgroud)

哪里lookupValue是UDF.使用存储过程时无法使用此类功能.同时你不能在UDF中做某些事情.这里要记住的基本事情是UDF:

  • 无法创建永久性更改
  • 不能改变数据

存储过程可以做那些事情.

对我来说,UDF的内联使用是UDF最重要的用法.


Tig*_*z32 13

存储过程 用作脚本.它们为您运行一系列命令,您可以安排它们在特定时间运行.

函数 用作方法.你传递了一些东西,它返回一个结果.应该小而快 - 它是否在飞行中.

  • 这是对两种快速而肮脏的思考方式的一个很好的总结. (2认同)
  • 确实是一个很好的总结 其他答案集中在两者的理论差异上,同时仍然不确定何时在实践中使用哪一个. (2认同)

Jai*_*arN 8

存储过程:

  • 就像是SQL Server中的微型程序.
  • 可以像select语句一样简单,也可以像添加,删除,更新和/或从数据库中的多个表中读取数据的长脚本一样复杂.
  • (可以实现循环和游标,它们都允许您使用较小的结果或逐行操作数据.)
  • 应该使用EXECEXECUTE声明调用.
  • 返回表变量,但我们不能使用OUT参数.
  • 支持交易.

功能:

  • 不能用于更新,删除或添加记录到数据库.
  • 只需返回单个值或表值.
  • 只能用于选择记录.但是,它可以在标准SQL中非常容易地调用,例如:

    SELECT dbo.functionname('Parameter1')
    
    Run Code Online (Sandbox Code Playgroud)

    要么

    SELECT Name, dbo.Functionname('Parameter1') FROM sysObjects
    
    Run Code Online (Sandbox Code Playgroud)
  • 对于简单的可重用选择操作,函数可以简化代码.只是要小心JOIN在你的函数中使用子句.如果您的函数有一个JOIN子句,并且您从另一个返回多个结果的select语句调用它,则该函数调用将JOIN 这些表一起用于结果集中返回的每一行.因此,尽管它们可以帮助简化某些逻辑,但如果它们没有得到正确使用,它们也可能成为性能瓶颈.

  • 使用OUT参数返回值.
  • 不支持交易.


Arn*_*shn 6

决定何时使用以下各点可能有所帮助 -

  1. 存储过程不能返回表变量,而函数可以这样做.

  2. 您可以使用存储过程来更改服务器环境参数,而使用您无法使用的功能.

干杯


Ach*_*les 6

像游标一样,SQL Server函数可以用作你的最后一个武器!它们确实存在性能问题,因此应尽可能避免使用表值函数.谈论性能是指在中型硬件上托管在服务器上的超过1,000,000条记录的表; 否则你不必担心功能造成的性能损失.

  1. 永远不要使用函数将结果集返回到外部代码(如ADO.Net)
  2. 尽可能使用views/stored procs组合.你可以使用DTA(数据库调优顾问)给你的建议(比如索引视图和统计数据)来恢复未来的成长性能问题 - 有时候!

有关进一步参考,请参阅:http://databases.aspfaq.com/database/should-i-use-a-view-a-stored-procedure-or-a-user-defined-function.html


Mah*_*are 5

用户定义的功能。

  1. 函数必须返回一个值。
  2. 将仅允许Select语句,不允许我们使用DML语句。
  3. 它将仅允许输入参数,不支持输出参数。
  4. 它将不允许我们使用try-catch块。
  5. 函数内不允许进行事务处理。
  6. 我们只能使用表变量,而不允许使用临时表。
  7. 无法从函数中调用存储过程。
  8. 可以从select语句中调用函数。
  9. UDF可以在join子句中用作结果集。

储存程序

  1. 存储过程可能会或不会返回值。
  2. 可以具有select语句以及DML语句,例如insert,update,delete等
  3. 它可以同时具有输入和输出参数。
  4. 对于异常处理,我们可以使用try catch块。
  5. 可以在存储过程中使用事务。
  6. 可以同时使用表变量和临时表。
  7. 存储过程可以调用函数。
  8. 无法从Select / Where / Having等语句中调用过程。Execute / Exec语句可用于调用/执行存储过程。
  9. 不能在Join子句中使用过程