函数与SQL Server中的存储过程

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

有人能告诉我为什么?

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

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

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

  • 函数遵循计算机的权限定义,因为它们必须返回一个值,不能改变它们作为参数(参数)接收的数据。 函数不允许改变任何东西,必须至less有一个参数,并且它们必须返回一个值。 存储过程不需要有参数,可以改变数据库对象,也不必返回值

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. | | +---------------------------------+----------------------------------------+ 

函数和存储过程服务于不同的目的。 虽然这不是最好的比喻,但是函数可以从字面上看作任何其他编程语言中使用的函数,但存储过程更像个别程序或批处理脚本。

function通常有一个输出和可选的input。 然后,输出可以用作另一个函数(SQL Server内置的DATEDIFF,LEN等)的input,或者作为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) 

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个即席查询。 同样,如果在column spec中指定了该函数,那么该函数将被SELECT所返回的每一行调用。

所以你需要小心编写函数。 如果你从一个函数的表中做SELECT,那么你需要问自己,在父存储过程还是其他一些SQL构造(如CASE … WHEN … ELSE …结束)。

当你想计算并返回一个用于其他SQL语句的值时,编写一个用户定义的函数; 当你想要的时候编写一个存储过程,而不是将一组可能复杂的SQL语句分组。 毕竟这是两个完全不同的用例!

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

  • 存储过程不能在Select语句中使用。
  • 存储过程支持延迟名称parsing。
  • 存储过程通常用于执行业务逻辑。
  • 存储过程可以返回任何数据types。
  • 存储过程可以接受比用户定义的函数更多的input参数。 存储过程最多可以有21,000个input参数。
  • 存储过程可以执行dynamicSQL。
  • 存储过程支持error handling。
  • 存储过程中可以使用非确定性函数。

  • 用户定义的函数可以在Select语句中使用。
  • 用户定义的函数不支持延迟名称parsing。
  • 用户定义的函数通常用于计算。
  • 用户定义的函数应该返回一个值。
  • 用户定义的function不能返回图像。
  • 用户定义的函数接受比存储过程更less的input参数。 UDF最多可以有1,023个input参数。
  • 临时表格不能在用户定义的函数中使用。
  • 用户定义的函数不能执行dynamicSQL。
  • 用户定义的函数不支持error handling。 在UDF中不允许RAISEERROR@@ERROR
  • 非确定性函数不能在UDF中使用。 例如, GETDATE()不能在UDF中使用。

基本差异

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

函数只能有input参数,而程序可以有input/输出参数。

函数采用一个input参数,但是存储过程可能需要input参数o。

函数可以从程序调用,而程序不能从函数调用。

进步差异

过程允许SELECT以及DML(INSERT / UPDATE / DELETE)语句,而Function只允许SELECT语句。

过程不能在SELECT语句中使用,而函数可以embedded在SELECT语句中。

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

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

内联函数可以作为视图的参数,并且可以在JOIN和其他行集操作中使用。

exception可以通过一个Procedure中的try-catch块来处理,而try-catch块不能在一个Function中使用。

我们可以在程序中进行事务pipe理,但是我们不能进入函数。

资源

用户定义的函数是sql server程序员可用的一个重要工具。 你可以像这样在SQL语句中内联使用它

 SELECT a, lookupValue(b), c FROM customers 

lookupValue将是一个UDF。 使用存储过程时,这种function是不可能的。 同时你不能在UDF内做某些事情。 这里要记住的基本的东西是UDF的:

  • 不能创造永久的变化
  • 不能改变数据

一个存储过程可以做这些事情。

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

存储过程 被用作脚本 。 他们为你运行一系列的命令,你可以安排他们在某些时候运行。

函数 被用作方法。 你传递一些东西,然后返回结果。 应该小而快 – 在飞行中。

要决定何时使用以下几点可能有所帮助 –

  1. 存储过程不能返回一个表variables在哪里function可以做到这一点。

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

干杯

像游标这样的SQL Server函数是用来作为最后的武器的! 他们确实有性能问题,因此应该尽可能地避免使用表值函数。 谈论性能是指在中级硬件服务器上托pipe超过1,000,000条logging的表格。 否则你不用担心function造成的性能打击。

  1. 切勿使用函数将结果集返回给外部代码(如ADO.Net)
  2. 尽可能使用views / stored procs组合。 您可以使用DTA(数据库优化顾问)为您提供的build议(如索引视图和统计信息) – 有时可以从未来的增长性能问题中恢复过来。

进一步的参考见: http : //databases.aspfaq.com/database/should-i-use-a-view-a-stored-procedure-or-a-user-defined-function.html

存储过程:

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

function:

  • 不能用于更新,删除或向数据库添加logging。
  • 只需返回一个值或一个表值。
  • 只能用于selectlogging。 但是,从标准SQL中可以非常容易地调用它,例如:

     SELECT dbo.functionname('Parameter1') 

    要么

     SELECT Name, dbo.Functionname('Parameter1') FROM sysObjects 
  • 对于简单的可重用select操作,函数可以简化代码。 只是要小心在你的函数中使用JOIN子句。 如果您的函数有一个JOIN子句,并且您从另一个返回多个结果的select语句中调用该函数,那么该函数将为这些表一起JOIN结果集中返回的每一行。 所以尽pipe它们可以有助于简化某些逻辑,但如果使用不当,也可能成为性能瓶颈。

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

从返回单个值的函数开始。 好的是你可以把经常使用的代码放到一个函数中,并把它们作为列返回给结果集。

然后,您可以使用一个函数作为参数化的城市列表。 dbo.GetCitiesIn(“NY”)返回一个可以用作连接的表。

这是一种组织代码的方式。 知道什么时候可以重复使用,什么时候浪费时间,只能通过反复试验和经验来获得。

另外,在SQL Server中,函数是一个好主意。 他们更快,可以相当强大。 内联和直接select。 小心不要过度使用。

  • 函数返回一个值,而不是存储过程。
  • select只在UDF中接受的语句,而不需要DML语句。
  • 存储过程接受任何语句以及DML语句。
  • UDF只允许input而不允许输出。
  • 存储过程允许input和输出。
  • 捕获块不能在UDF中使用,但可以在存储过程中使用。
  • UDF中的函数中不允许交易,但是在存储过程中,它们是允许的。
  • 只有表格variables可以在UDF中使用,而不能在临时表格中使用。
  • 存储过程允许表variables和临时表。
  • UDF不允许从函数调用存储过程,而存储过程允许调用函数。
  • UDF用于连接子句中,而存储过程不能用于连接子句中。
  • 存储过程将始终允许归零。 相反,UDF具有必须回到预定点的价值。
  • 函数可以用在select语句中,而程序不能。

  • 存储过程同时接受input和输出参数,但函数仅接受input参数。

  • 函数无法返回types为text,ntext,image&timestamps的值,而这些值可以在程序中使用。

  • 函数可以在create table中用作用户定义的数据types,但是程序不能。

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

这里的getsal是一个用户定义的函数,它返回一个工资types,当创build表时没有为工资types分配存储,并且getsal函数也没有执行,但是当我们从这个表中取得一些值时,gets函数get被执行,返回types作为结果集返回。

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

如果你被存储过程调用其他存储过程,你可能会遇到这个问题。 如果嵌套存储过程只返回一个数据集,则可以用一个表值函数replace,这样就不会再出现这个错误。

这是我们应该保持业务逻辑不在数据库中的另一个原因

存储过程和用户​​定义函数的区别

在这里输入图像描述

在SQL Server中,函数和存储过程是两种不同types的实体。

function:在SQL Server数据库中,函数用于执行一些操作,操作立即返回结果。 函数有两种types:

  1. 系统定义

  2. 用户自定义

存储过程:在SQL Server中,存储过程存储在服务器中,可以返回零值,单值和多值。 存储过程有两种types:

  1. 系统存储过程
  2. 用户定义的程序