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

Posted

技术标签:

【中文标题】MySQL存储过程与函数,我啥时候使用?【英文标题】:MySQL stored procedure vs function, which would I use when?MySQL存储过程与函数,我什么时候使用? 【发布时间】:2011-04-14 05:44:34 【问题描述】:

我正在研究 mysql 存储过程和函数。真正的区别是什么?

它们看起来很相似,但是一个函数有更多的限制。

我可能错了,但似乎存储过程可以做所有事情,而存储函数可以做的更多。为什么/何时使用过程与函数?

【问题讨论】:

【参考方案1】:

过程和函数之间最普遍的区别在于它们的调用方式和目的不同:

    过程不返回值。相反,它通过 CALL 语句调用以执行操作,例如修改表或处理检索到的记录。 在表达式中调用函数,并将单个值直接返回给要在表达式中使用的调用者。 您不能使用 CALL 语句调用函数,也不能在表达式中调用过程。

例程创建的语法因过程和函数而有所不同:

    过程参数可以定义为仅输入、仅输出或两者兼有。这意味着一个过程可以通过使用输出参数将值传回给调用者。可以在 CALL 语句之后的语句中访问这些值。函数只有输入参数。因此,虽然过程和函数都可以有参数,但过程参数的声明与函数的不同。

    函数返回值,所以函数定义中必须有一个RETURNS子句来表示返回值的数据类型。此外,函数体内必须至少有一个 RETURN 语句才能将值返回给调用者。 RETURNS 和 RETURN 不出现在过程定义中。

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

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

    将参数指定为 IN、OUT 或 INOUT 仅对 PROCEDURE 有效。对于 FUNCTION,参数始终被视为 IN 参数。

    如果参数名前没有给出关键字,则默认为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(您将语句构造为字符串然后执行它们)。 (Dynamic SQL in MySQL stored routines)

FUNCTION 和 STORED PROCEDURE 之间一些更有趣的区别:

    (这个点是copied from a blogpost.) 存储过程是预编译的执行计划,而 as 函数不是。函数在运行时解析和编译。存储过程,以伪代码形式存储在数据库中,即编译后的形式。

    我不确定这一点。) 存储过程具有安全性和减少网络 流量,我们也可以在任何号码中调用存储过程。的 一次申请。 reference

    函数通常用于计算,其中 过程通常用于执行业务逻辑。

    函数不能影响数据库的状态 (函数中不允许显式或隐式提交或回滚的语句) 然而 存储过程可以使用提交等影响数据库的状态。 参考:J.1. Restrictions on Stored Routines and Triggers

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

    存储函数不能递归,而存储过程可以。 注意:递归存储过程默认禁用,但可以通过将 max_sp_recursion_depth 服务器系统变量设置为非零值在服务器上启用。请参阅Section 5.2.3, “System Variables”,了解更多信息。

    在存储函数或触发器中,不允许修改已被使用的表 (用于读取或写入)由调用函数或触发器的语句。 很好的例子:How to Update same table on deletion in MYSQL?

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

【讨论】:

@GrijeshChauhan,你说“函数在运行时解析和编译”是什么意思 @Pacerier 意味着 MySQL 中的函数类似于脚本,它们可以即时编译和执行。我从一些blog post 复制了它,但没有执行任何实际操作来检查这种行为。 在过程中你可以传递一个out变量作为参数,然后用select语句调用它 我认为这个答案底部的要点#4是过程和功能之间差异的核心。程序可以更改数据库,函数不能。所有其他差异只是为了更有效地服务于该目的。【参考方案2】:

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

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

【讨论】:

函数有哪些限制? 啊,我在这里找到了一些不错的信息:dev.mysql.com/doc/refman/5.0/en/…【参考方案3】:

一个显着的区别是您可以在 SQL 查询中包含 function,但 stored procedures 只能使用 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)

Sproc 示例:

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)

【讨论】:

你的函数有两个返回?我的意思是这条线是什么? RETURNS CHAR(50) DETERMINISTIC ? RETURNS CHAR(50) 说明将返回什么类型的数据。 RETURN CONCAT(... 是要返回的数据。两者都是需要的。需要DETERMINISTIC 声明底层数据不会被修改。【参考方案4】:

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

使用 CALL 查询执行过程。

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

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

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

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

【讨论】:

以上是关于MySQL存储过程与函数,我啥时候使用?的主要内容,如果未能解决你的问题,请参考以下文章

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

MySQL基础_存储过程与函数

MySQL数据库之存储过程与存储函数

争议?MySQL存储过程与函数,封装,体,完整详细可收藏

mysql 与oracle中的存储过程及函数有啥区别,尽可能详细哦

我啥时候应该在 PL/SQL 中使用过程或函数?