我学习函数和存储过程已经有一段时间了,但我不知道为什么以及何时应该使用函数或存储过程。它们对我来说看起来一样,也许是因为我对此有点新手。
有人能告诉我为什么吗?
我学习函数和存储过程已经有一段时间了,但我不知道为什么以及何时应该使用函数或存储过程。它们对我来说看起来一样,也许是因为我对此有点新手。
有人能告诉我为什么吗?
函数是计算值,不能对环境进行永久性更改SQL Server
(即不允许INSERT
或UPDATE
允许语句)。
如果函数SQL
返回标量值,则可以在语句中内联使用,如果返回结果集,则可以加入函数。
评论中值得注意的一点,总结了答案。感谢@Sean K Anderson:
函数遵循计算机科学的定义,因为它们必须返回一个值,并且不能更改它们作为参数(参数)接收的数据。函数不允许改变任何东西,必须至少有一个参数,并且它们必须返回一个值。存储过程不必有参数,可以更改数据库对象,也不必返回值。
SP和UDF的区别如下:
存储过程 (SP) | 功能(UDF - 用户定义) |
---|---|
SP 可以返回零、单个或多个值。 | 函数必须返回单个值(可以是标量或表)。 |
我们可以在 SP 中使用事务。 | 我们不能在 UDF 中使用事务。 |
SP 可以有输入/输出参数。 | 仅输入参数。 |
我们可以从 SP 调用函数。 | 我们不能从函数中调用 SP。 |
我们不能在 SELECT/WHERE/HAVING 语句中使用 SP。 | 我们可以在 SELECT/WHERE/HAVING 语句中使用 UDF。 |
我们可以使用 SP 中的 Try-Catch 块进行异常处理。 | 我们不能在 UDF 中使用 Try-Catch 块。 |
函数和存储过程有不同的用途。虽然这不是最好的类比,但函数可以从字面上视为您在任何编程语言中使用的任何其他函数,但存储过程更像是单个程序或批处理脚本。
函数通常有一个输出和可选的输入。然后可以将输出用作另一个函数(SQL Server 内置,如 DATEDIFF、LEN 等)的输入,或用作 SQL 查询的谓词 - 例如,SELECT a, b, dbo.MyFunction(c) FROM table
或SELECT 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 个即席查询。同样,如果在列规范中指定时调用该函数,则将为 SELECT 返回的每一行调用该函数。
所以你确实需要小心编写函数。如果您从函数中的表中执行 SELECT,您需要问自己是否可以使用父存储过程中的 JOIN 或其他一些 SQL 构造(例如 CASE ... WHEN ... ELSE ...结尾)。
存储过程和用户定义函数的区别:
RAISEERROR
OR 。@@ERROR
GETDATE()
不能在 UDF 中使用。当你想计算并返回一个值用于其他 SQL 语句时,编写一个用户定义的函数;当您需要时编写存储过程是对一组可能很复杂的 SQL 语句进行分组。毕竟,这是两个完全不同的用例!
存储过程 | 功能(用户定义的功能) |
---|---|
过程可以返回 0、单个或多个值 | 函数只能返回单个值 |
程序可以有输入、输出参数 | 函数只能有输入参数 |
不能从函数调用过程 | 函数可以从过程中调用 |
过程允许在其中选择以及 DML 语句 | 函数中只允许选择语句 |
异常可以通过过程中的 try-catch 块来处理 | Try-catch 块不能在函数中使用 |
能在手续上进行交易管理 | 我们不能在函数中进行事务管理 |
不能在 select 语句中使用过程 | 函数可以嵌入到 select 语句中 |
过程可以影响数据库的状态意味着它可以对数据库执行CRUD操作 | 函数不能影响数据库的状态意味着它不能对数据库执行CRUD操作 |
过程可以使用临时表 | 函数不能使用临时表 |
程序可以改变服务器环境参数 | 函数不能改变环境参数 |
当我们需要时可以使用过程,而不是对一组可能复杂的 SQL 语句进行分组 | 当我们想要计算并返回一个值以供其他 SQL 语句使用时,可以使用函数 |
基本区别
函数必须返回一个值,但在存储过程中它是可选的(过程可以返回零或 n 个值)。
函数只能有输入参数,而过程可以有输入/输出参数。
函数需要一个输入参数,这是强制性的,但存储过程可能需要 o 到 n 个输入参数。
函数可以从过程中调用,而过程不能从函数中调用。
提前差价
过程允许在其中使用 SELECT 以及 DML(INSERT/UPDATE/DELETE) 语句,而函数只允许在其中使用 SELECT 语句。
过程不能在 SELECT 语句中使用,而函数可以嵌入在 SELECT 语句中。
存储过程不能在 WHERE/HAVING/SELECT 部分的任何地方的 SQL 语句中使用,而函数可以。
返回表的函数可以被视为另一个行集。这可以在与其他表的 JOIN 中使用。
内联函数可以作为带有参数的视图,并且可以用于 JOIN 和其他 Rowset 操作。
异常可以由过程中的 try-catch 块处理,而 try-catch 块不能在函数中使用。
我们可以在过程中进行事务管理,而不能在函数中进行。
用户定义函数是 sql server 程序员可用的重要工具。您可以像这样在 SQL 语句中内联使用它
SELECT a, lookupValue(b), c FROM customers
lookupValue
UDF在哪里。使用存储过程时,这种功能是不可能的。同时你不能在 UDF 中做某些事情。这里要记住的基本内容是 UDF:
存储过程可以做这些事情。
对我来说,UDF 的内联用法是 UDF 最重要的用法。
存储过程 用作脚本。它们为您运行一系列命令,您可以安排它们在特定时间运行。通常运行多个 DML 语句,如 INSERT、UPDATE、DELETE 等,甚至 SELECT。
函数 用作方法。你传给它一些东西,它会返回一个结果。应该小而快 - 即时完成。通常在 SELECT 语句中使用。
存储过程:
EXEC
orEXECUTE
语句。OUT
参数。功能:
只能用于选择记录。但是,它可以很容易地从标准 SQL 中调用,例如:
SELECT dbo.functionname('Parameter1')
或者
SELECT Name, dbo.Functionname('Parameter1') FROM sysObjects
对于简单的可重用选择操作,函数可以简化代码。请注意在函数中使用JOIN
子句。如果您的函数有一个JOIN
子句,并且您从另一个返回多个结果的 select 语句中调用它,则该函数调用将JOIN
这些表一起用于结果集中返回的每一行。因此,尽管它们有助于简化某些逻辑,但如果使用不当,它们也可能成为性能瓶颈。
OUT
使用参数返回值。用户定义函数。
存储过程
SQL Server 函数(如游标)旨在用作您的最后武器!它们确实存在性能问题,因此应尽可能避免使用表值函数。谈论性能就是谈论在中级硬件的服务器上托管的具有超过 1,000,000 条记录的表;否则您无需担心功能造成的性能损失。
如需进一步参考,请参阅:http ://databases.aspfaq.com/database/should-i-use-a-view-a-stored-procedure-or-a-user-defined-function.html
要决定何时使用以下几点可能会有所帮助-
存储过程不能返回一个表变量,而 as 函数可以做到这一点。
您可以使用存储过程来更改服务器环境参数,而使用您不能使用的功能。
干杯
从返回单个值的函数开始。好处是您可以将常用代码放入函数中,并将它们作为结果集中的列返回。
然后,您可以将函数用于城市的参数化列表。dbo.GetCitiesIn("NY") 返回一个可以用作连接的表。
这是一种组织代码的方式。只有通过反复试验和经验才能知道什么时候可以重用,什么时候浪费时间。
此外,函数在 SQL Server 中也是一个好主意。它们速度更快,并且可以非常强大。内联和直接选择。注意不要过度使用。
这是更喜欢函数而不是存储过程的实际原因。如果您有一个存储过程需要另一个存储过程的结果,则必须使用 insert-exec 语句。这意味着您必须创建一个临时表并使用一条exec
语句将存储过程的结果插入到临时表中。很乱。这样做的一个问题是insert-execs 不能嵌套。
如果您遇到调用其他存储过程的存储过程,您可能会遇到这种情况。如果嵌套存储过程只返回一个数据集,则可以将其替换为表值函数,您将不再收到此错误。
(这是我们应该将业务逻辑排除在数据库之外的另一个原因)
我意识到这是一个非常古老的问题,但我没有看到任何答案中提到的一个关键方面:内联查询计划。
函数可以...
标量:
CREATE FUNCTION ... RETURNS scalar_type AS BEGIN ... END
多语句表值:
CREATE FUNCTION ... RETURNS @r TABLE(...) AS BEGIN ... END
内联表值:
CREATE FUNCTION ... RETURNS TABLE AS RETURN SELECT ...
第三种(内联表值)被查询优化器本质上视为(参数化)视图,这意味着从查询中引用函数类似于复制粘贴函数的 SQL 主体(实际上没有复制粘贴),导致获得以下好处:
上述可能会导致潜在的显着性能节省,尤其是在组合多个级别的功能时。
注意:看起来 SQL Server 2019 也将引入某种形式的标量函数内联。
函数可以在选择语句中使用,而 as 过程不能。
存储过程接受输入和输出参数,但函数只接受输入参数。
函数不能像过程一样返回文本、ntext、图像和时间戳类型的值。
函数可以在 create table 中用作用户定义的数据类型,但过程不能。
***例如:-创建table <tablename>(name varchar(10),salary getsal(name))
这里的getsal是一个用户定义的函数,它返回一个salary类型,当创建表时没有为salary类型分配存储空间,并且getsal函数也没有执行,但是当我们从这个表中获取一些值时,getsal函数get被执行并且返回类型作为结果集返回。
通常使用存储过程对性能更好。例如,在以前版本的 SQL Server 中,如果将函数置于 JOIN 条件下,基数估计为 1(SQL 2012 之前)和 100(SQL 2012 之后和 SQL 2017 之前),并且引擎可能会生成错误的执行计划。
此外,如果将其放在 WHERE 子句中,SQL 引擎可能会生成错误的执行计划。
在 SQL 2017 中,Microsoft 引入了称为交错执行的功能,以产生更准确的估计,但存储过程仍然是最佳解决方案。
有关更多详细信息,请参阅 Joe Sack 的以下文章 https://techcommunity.microsoft.com/t5/sql-server/introducing-interleaved-execution-for-multi-statement-table/ba-p/385417
在 SQL Server 中,函数和存储过程是两种不同类型的实体。
函数:在 SQL Server 数据库中,函数用于执行一些动作,动作立即返回结果。函数有两种类型:
系统定义
用户自定义
存储过程:在 SQL Server 中,存储过程存储在服务器中,可以返回零值、单个值和多个值。存储过程有两种类型: