文档首页
MySQL 9.0 参考手册
相关文档 下载本手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
信息 (Gzip) - 4.0Mb
信息 (Zip) - 4.0Mb


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

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

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. 是否有与使用 mod_plsql 作为 Apache 上的网关直接与数据库中的存储过程通信的 MySQL 等效项?
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 中是否有等效于使用 mod_plsql 作为 Apache 上的网关直接与数据库中的存储过程通信的方法?

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.8 节“存储程序二进制日志记录” 中有详细描述。

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 活动中部分更新,但由于发生的错误,副本服务器没有更新。解决方法是在执行函数的 DML 操作时使用 IGNORE 关键字,以便忽略在源服务器上导致错误的更新,并将不会导致错误的更新复制到副本服务器。

A.4.27.

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

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

A.4.28.

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

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

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

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