MySQL存储过程与函数,我什么时候使用?

我正在查看MySQL存储过程和函数。真正的区别是什么?

它们看起来很相似,但功能有更多的局限性。

我可能错了,但似乎存储过程可以做任何事情,而且比存储函数做得更多。为什么/何时使用过程而不是函数?

123482 次浏览

存储函数可以在查询中使用。然后,您可以将其应用于每一行或WHERE子句中。

使用调用查询执行过程。

存储过程不能与普通SQL混合,而存储函数则可以。

例如,如果get_foo()是一个过程,则SELECT get_foo(myColumn) FROM mytable无效,但如果get_foo()是一个函数,则可以这样做。代价是功能比程序有更多的限制。

一个显著的区别是,您可以在SQL查询中包括功能,但存储过程只能用CALL语句调用:

UDF示例:

CREATE FUNCTION hello (s CHAR(20))
RETURNS CHAR(50) DETERMINISTIC
RETURN CONCAT('Hello, ',s,'!');
Query OK, 0 rows affected (0.00 sec)


CREATE TABLE names (id int, name varchar(20));
INSERT INTO names VALUES (1, 'Bob');
INSERT INTO names VALUES (2, 'John');
INSERT INTO names VALUES (3, 'Paul');


SELECT hello(name) FROM names;
+--------------+
| hello(name)  |
+--------------+
| Hello, Bob!  |
| Hello, John! |
| Hello, Paul! |
+--------------+
3 rows in set (0.00 sec)

存储过程示例:

delimiter //


CREATE PROCEDURE simpleproc (IN s CHAR(100))
BEGIN
SELECT CONCAT('Hello, ', s, '!');
END//
Query OK, 0 rows affected (0.00 sec)


delimiter ;


CALL simpleproc('World');
+---------------------------+
| CONCAT('Hello, ', s, '!') |
+---------------------------+
| Hello, World!             |
+---------------------------+
1 row in set (0.00 sec)

过程和函数之间最常见的区别是它们的调用方式不同,并且用于不同的目的:

  1. 过程不返回值。相反,使用CALL语句调用它来执行操作,如修改表或处理检索到的记录。
  2. 函数在表达式中调用,并直接向调用方返回要在表达式中使用的单个值。
  3. 不能使用CALL语句调用函数,也不能在表达式中调用过程。

对于过程和函数,例程创建的语法略有不同:

  1. 过程参数可以定义为仅输入、仅输出或两者。这意味着过程可以使用OUTPUT参数将值传递回调用方。可以在CALL语句后面的语句中访问这些值。函数只有输入参数。因此,尽管过程和函数都可以有参数,但过程参数声明与函数参数声明不同。
  2. 函数返回值,因此在函数定义中必须有一个RETURNS子句来指示返回值的数据类型。此外,函数体中必须至少有一个return语句才能向调用方返回值。RETURNS和RETURN不出现在过程定义中。

    • 要调用存储过程,请使用CALL statement。要调用存储函数,请在表达式中引用它。该函数在表达式计算过程中返回一个值。

    • 过程使用CALL语句调用,并且只能使用OUTPUT变量传回值。就像任何其他函数一样,可以从语句内部调用函数(即,通过调用函数的名称),并且可以返回标量值。

    • 将参数指定为IN、OUT或INOUT仅对过程有效。对于一个函数,参数总是被认为是内参数。

    如果在参数名称之前没有给出关键字,则默认情况下它是IN参数。 存储函数的参数前面没有IN、OUT或INOUT.所有函数参数都被视为IN参数。

要定义存储过程或函数,请分别使用CREATE PROCEDURE或CREATE FUNCTION:

CREATE PROCEDURE proc_name ([parameters])
[characteristics]
routine_body




CREATE FUNCTION func_name ([parameters])
RETURNS data_type       // diffrent
[characteristics]
routine_body

存储过程(不是函数)的MySQL扩展是一个过程可以生成一个结果集,甚至多个结果集,调用方处理这些结果集的方式与处理SELECT语句的结果的方式相同。但是,这类结果集的内容不能直接在表达式中使用。

存储例程(指存储过程和存储函数)与特定数据库相关联,就像表或视图一样。删除数据库时,也会删除数据库中的所有存储例程。

存储过程和函数不共享相同的命名空间。,在数据库中可以有同名的过程和函数。

在存储过程中可以使用动态SQL,但不能在函数或触发器中使用。

SQL预准备语句(PREPARE、EXECUTE、DEALLOCATE PREPARE)可以在存储过程中使用,但不能在存储函数或触发器中使用。因此,存储函数和触发器不能使用动态SQL(将语句构造为字符串,然后执行它们)。(MySQL存储例程中的动态SQL)

函数和存储过程之间的一些更有趣的区别:

  1. 这一点是从一篇博客文章中复制的。) 存储过程是预编译的执行计划,而AS函数则不是。在运行时解析和编译的函数。存储过程,作为伪代码存储在数据库中,即编译形式。

  2. 这一点我不太清楚。
    存储过程具有安全性和减少网络 交通,我们也可以在任何没有调用存储过程。的 每次应用程序。提及

  3. 函数通常用于计算,如 过程通常用于执行业务逻辑。

  4. 函数不能影响数据库的状态 (函数中不允许执行显式或隐式提交或回滚的语句) 而 存储过程可以使用COMMIT等影响数据库的状态。
    参考:J.1。对存储例程和触发器的限制

  5. 函数不能使用FLUSH语句,而存储过程可以。

  6. 存储函数不能是递归的,而存储过程可以是递归的。 注意:递归存储过程在默认情况下是禁用的,但通过将服务器系统变量“最大_SP_递归_深度”设置为非零值,可在服务器上启用该过程。有关详细信息,请参阅第5.2.3节“系统变量”

  7. 在存储函数或触发器中,不允许修改正在使用的表 (用于读或写)调用函数或触发器的语句。 很好的例子:如何在MySQL中删除时更新相同的表?

注意:尽管某些限制通常适用于存储函数和触发器而不适用于存储过程,但如果从存储函数或触发器中调用存储过程,则这些限制也适用于它们。例如,尽管可以在存储过程中使用FLUSH,但不能从存储函数或触发器调用此类存储过程。

存储过程可以递归调用,而存储函数不能

除了上面给出的答案外,我还想补充一点

函数可以与其他函数和表达式结合使用,也可以以嵌套的方式使用(简而言之,它们可以以非常复杂的形式使用,以完成我们想要的工作)。

同样的事情可以在过程中实现,但在过程中,我们必须完成该过程内部完成的所有工作,这意味着以单一的方式编写代码。(而IN函数可以用于每个任务;可以实现新的功能)。所以最后我们可以通过使用不同功能的组合来完成任务。