文档首页
MySQL 8.4 参考手册
相关文档 下载本手册

MySQL 8.4 参考手册  /  MySQL 8.4 常见问题解答  /  MySQL 8.4 常见问题解答:存储过程和函数

A.4 MySQL 8.4 常见问题解答:存储过程和函数

A.4.1. MySQL 是否支持存储过程和函数?
A.4.2. 在哪里可以找到 MySQL 存储过程和存储函数的文档?
A.4.3. 是否有关于 MySQL 存储过程的讨论论坛?
A.4.4. 在哪里可以找到 ANSI SQL 2003 存储过程规范?
A.4.5. 如何管理存储例程?
A.4.6. 是否有一种方法可以查看给定数据库中的所有存储过程和存储函数?
A.4.7. 存储过程存储在哪里?
A.4.8. 是否可以将存储过程或存储函数分组到包中?
A.4.9. 存储过程可以调用另一个存储过程吗?
A.4.10. 存储过程可以调用触发器吗?
A.4.11. 存储过程可以访问表吗?
A.4.12. 存储过程是否有用于引发应用程序错误的语句?
A.4.13. 存储过程是否提供异常处理?
A.4.14. MySQL 存储例程可以返回结果集吗?
A.4.15. 存储过程是否支持 WITH RECOMPILE?
A.4.16. 是否有 MySQL 等效项可以使用 mod_plsql 作为 Apache 上的网关直接与数据库中的存储过程通信?
A.4.17. 我可以将数组作为输入传递给存储过程吗?
A.4.18. 我可以将游标作为 IN 参数传递给存储过程吗?
A.4.19. 我可以从存储过程中返回游标作为 OUT 参数吗?
A.4.20. 我可以为了调试目的打印出存储例程中变量的值吗?
A.4.21. 我可以在存储过程中提交或回滚事务吗?
A.4.22. MySQL 存储过程和函数是否可以与复制一起使用?
A.4.23. 在复制源服务器上创建的存储过程和函数是否会复制到副本?
A.4.24. 存储过程和函数内部发生的操作是如何复制的?
A.4.25. 将存储过程和函数与复制一起使用是否有特殊的安全要求?
A.4.26. 复制存储过程和函数操作有哪些限制?
A.4.27. 上述限制是否会影响 MySQL 执行时间点恢复的能力?
A.4.28. 正在采取哪些措施来纠正上述限制?

A.4.1.

MySQL 是否支持存储过程和函数?

是的。MySQL 支持两种类型的存储例程,存储过程和存储函数。

A.4.2.

在哪里可以找到 MySQL 存储过程和存储函数的文档?

参见 第 27.2 节“使用存储例程”。

A.4.3.

是否有关于 MySQL 存储过程的讨论论坛?

是的。参见 https://forums.mysql.com/list.php?98

A.4.4.

在哪里可以找到 ANSI SQL 2003 存储过程规范?

遗憾的是,官方规范不是免费提供的(ANSI 将其提供给购买者)。但是,有一些书籍,例如 Peter Gulutzan 和 Trudy Pelzer 合著的《SQL-99 Complete, Really》,提供了对该标准的全面概述,包括对存储过程的介绍。

A.4.5.

如何管理存储例程?

对存储例程使用清晰的命名方案始终是一个好习惯。您可以使用 CREATE [FUNCTION|PROCEDURE]ALTER [FUNCTION|PROCEDURE]DROP [FUNCTION|PROCEDURE]SHOW CREATE [FUNCTION|PROCEDURE] 管理存储过程。您可以使用 INFORMATION_SCHEMA 数据库中的 ROUTINES 表获取有关现有存储过程的信息(请参阅 第 28.3.30 节“INFORMATION_SCHEMA ROUTINES 表”)。

A.4.6.

是否有一种方法可以查看给定数据库中的所有存储过程和存储函数?

是的。对于名为 dbname 的数据库,请在 INFORMATION_SCHEMA.ROUTINES 表上使用以下查询

SELECT ROUTINE_TYPE, ROUTINE_NAME
    FROM INFORMATION_SCHEMA.ROUTINES
    WHERE ROUTINE_SCHEMA='dbname';

有关更多信息,请参阅 第 28.3.30 节“INFORMATION_SCHEMA ROUTINES 表”

可以使用 SHOW CREATE FUNCTION(对于存储函数)或 SHOW CREATE PROCEDURE(对于存储过程)查看存储例程的主体。有关更多信息,请参阅 第 15.7.7.10 节“SHOW CREATE PROCEDURE 语句”

A.4.7.

存储过程存储在哪里?

存储过程存储在 mysql.routinesmysql.parameters 表中,它们是数据字典的一部分。您不能直接访问这些表。而是查询 INFORMATION_SCHEMA ROUTINESPARAMETERS 表。参见 第 28.3.30 节“INFORMATION_SCHEMA ROUTINES 表”第 28.3.20 节“INFORMATION_SCHEMA PARAMETERS 表”

您还可以使用 SHOW CREATE FUNCTION 获取有关存储函数的信息,并使用 SHOW CREATE PROCEDURE 获取有关存储过程的信息。参见 第 15.7.7.10 节“SHOW CREATE PROCEDURE 语句”

A.4.8.

是否可以将存储过程或存储函数分组到包中?

不可以。MySQL 不支持此功能。

A.4.9.

存储过程可以调用另一个存储过程吗?

是的。

A.4.10.

存储过程可以调用触发器吗?

存储过程可以执行 SQL 语句,例如 UPDATE,从而激活触发器。

A.4.11.

存储过程可以访问表吗?

是的。存储过程可以根据需要访问一个或多个表。

A.4.12.

存储过程是否有用于引发应用程序错误的语句?

是的。MySQL 实现了 SQL 标准的 SIGNALRESIGNAL 语句。参见 第 15.6.7 节“条件处理”

A.4.13.

存储过程是否提供异常处理?

MySQL 根据 SQL 标准实现了 HANDLER 定义。有关详细信息,请参阅 第 15.6.7.2 节“DECLARE ... HANDLER 语句”

A.4.14.

MySQL 存储例程可以返回结果集吗?

**存储过程**可以,但存储函数不可以。如果您在存储过程中执行普通的 SELECT,结果集将直接返回给客户端。您需要使用 MySQL 4.1(或更高版本)客户端/服务器协议才能实现此功能。这意味着,例如,在 PHP 中,您需要使用 mysqli 扩展而不是旧的 mysql 扩展。

A.4.15.

存储过程是否支持 WITH RECOMPILE

不支持。

A.4.16.

MySQL 中是否有等效于在 Apache 上使用 mod_plsql 作为网关直接与数据库中的存储过程通信的方法?

MySQL 中没有等效方法。

A.4.17.

我可以将数组作为输入传递给存储过程吗?

不支持。

A.4.18.

我可以将游标作为 IN 参数传递给存储过程吗?

游标只能在存储过程中使用。

A.4.19.

我可以从存储过程中返回游标作为 OUT 参数吗?

游标只能在存储过程中使用。但是,如果您没有在 SELECT 上打开游标,则结果会直接发送到客户端。您还可以使用 SELECT INTO 将数据存储到变量中。请参阅 第 15.2.13 节,“SELECT 语句”

A.4.20.

我可以为了调试目的在存储例程中打印出变量的值吗?

是的,您可以在**存储过程**中执行此操作,但不能在存储函数中执行此操作。如果您在存储过程中执行普通的 SELECT,结果集将直接返回给客户端。您必须使用 MySQL 4.1(或更高版本)客户端/服务器协议才能实现此功能。这意味着,例如,在 PHP 中,您需要使用 mysqli 扩展而不是旧的 mysql 扩展。

A.4.21.

我可以在存储过程中提交或回滚事务吗?

是的。但是,您不能在存储函数中执行事务性操作。

A.4.22.

MySQL 存储过程和函数是否可以与复制一起使用?

是的,在存储过程和函数中执行的标准操作会从复制源服务器复制到副本。但也有一些限制,这些限制在 第 27.7 节,“存储程序二进制日志记录” 中详细介绍。

A.4.23.

在复制源服务器上创建的存储过程和函数是否会复制到副本?

是的,通过在复制源服务器上执行的常规 DDL 语句创建的存储过程和函数会复制到副本,以便对象存在于两台服务器上。存储过程和函数的 ALTERDROP 语句也会被复制。

A.4.24.

如何在存储过程和函数内部进行的操作进行复制?

MySQL 会记录存储过程中发生的每个 DML 事件,并将这些单独的操作复制到副本。对执行存储过程的实际调用不会被复制。

更改数据的存储函数将记录为函数调用,而不是记录为每个函数内部发生的 DML 事件。

A.4.25.

将存储过程和函数与复制一起使用是否有特殊的安全要求?

是的。因为副本有权执行从源的二进制日志中读取的任何语句,所以在将存储函数与复制一起使用时存在特殊的安全约束。如果复制或二进制日志记录(用于时间点恢复)处于活动状态,则 MySQL DBA 可以选择以下两种安全选项

  1. 任何希望创建存储函数的用户都必须被授予 SUPER 权限。

  2. 或者,DBA 可以将 log_bin_trust_function_creators 系统变量设置为 1,这将允许任何具有标准 CREATE ROUTINE 权限的用户创建存储函数。

A.4.26.

复制存储过程和函数操作存在哪些限制?

嵌入在存储过程中的非确定性(随机)或基于时间的操作可能无法正确复制。根据其本身的性质,随机生成的结果是不可预测的,也无法完全复制;因此,复制到副本的随机操作不会镜像在源上执行的操作。将存储函数声明为 DETERMINISTIC 或将 log_bin_trust_function_creators 系统变量设置为 0 可防止调用产生随机值的随机操作。

此外,基于时间的操作无法在副本上复制,因为存储过程中此类操作的计时无法通过用于复制的二进制日志复制。它只记录 DML 事件,而不考虑时间约束。

最后,在大型 DML 操作(例如批量插入)期间发生错误的非事务性表可能会遇到复制问题,因为源可能会从 DML 活动中部分更新,但由于发生的错误,副本不会更新。解决方法是使用 IGNORE 关键字执行函数的 DML 操作,以便忽略在源上导致错误的更新,并将不会导致错误的更新复制到副本。

A.4.27.

上述限制是否会影响 MySQL 执行时间点恢复的能力?

影响复制的相同限制也会影响时间点恢复。

A.4.28.

正在采取哪些措施来纠正上述限制?

您可以选择基于语句的复制或基于行的复制。原始复制实现基于基于语句的二进制日志记录。基于行的二进制日志记录解决了前面提到的限制。

**混合**复制也可用(通过使用 --binlog-format=mixed 启动服务器)。这种混合形式的复制“知道”何时可以安全地使用语句级复制,或者何时需要行级复制。

有关其他信息,请参阅 第 19.2.1 节,“复制格式”