A.4 MySQL 5.7 FAQ:存储过程和函数


**A.4.1. **
MySQL 5.7 是否支持存储过程和函数?
是。 MySQL 5.7 支持两种类型的存储例程,存储过程和存储函数。

**A.4.2. **
我在哪里可以找到 MySQL 存储过程和存储函数的文档?
See 第 23.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. **
您如何 Management 存储的例程?
对您的存储例程使用明确的命名方案始终是一个好习惯。您可以使用CREATE [FUNCTION|PROCEDURE]ALTER [FUNCTION|PROCEDURE]DROP [FUNCTION|PROCEDURE]SHOW CREATE [FUNCTION|PROCEDURE]Management 存储过程。您可以使用INFORMATION_SCHEMA数据库中的ROUTINEStable 获取有关现有存储过程的信息(请参阅第 24.21 节“ INFORMATION_SCHEMA ROUTINEStable”)。

**A.4.6. **
是否可以查看给定数据库中的所有存储过程和存储函数?
是。对于名为* dbname *的数据库,请在INFORMATION_SCHEMA.ROUTINEStable 上使用以下查询:
SELECT ROUTINE_TYPE,ROUTINE_NAME
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_SCHEMA='dbname';
有关更多信息,请参见第 24.21 节“ INFORMATION_SCHEMA ROUTINEStable”
可以使用显示创建功能(对于存储的函数)或显示创建步骤(对于存储的过程)查看存储例程的主体。有关更多信息,请参见第 13.7.5.9 节“ SHOW CREATE PROCEDURE 语句”

**A.4.7. **
存储过程存储在哪里?
mysql系统数据库的proctable 中。但是,您不应直接访问系统数据库中的 table。而是,查询INFORMATION_SCHEMA ROUTINESPARAMETERStable。参见第 24.21 节“ INFORMATION_SCHEMA ROUTINEStable”第 24.15 节“ INFORMATION_SCHEMA PARAMETERStable”
您还可以使用显示创建功能获取有关存储函数的信息,并使用显示创建步骤获取有关存储过程的信息。参见第 13.7.5.9 节“ SHOW CREATE PROCEDURE 语句”

**A.4.8. **
可以将存储过程或存储函数分组到包中吗?
否。 MySQL 5.7 不支持此功能。

**A.4.9. **
一个存储过程可以调用另一个存储过程吗?
Yes.

**A.4.10. **
存储过程可以调用触发器吗?
存储过程可以执行导致触发触发器的 SQL 语句,例如UPDATE

**A.4.11. **
存储过程可以访问 table 吗?
是。存储过程可以根据需要访问一个或多个 table。

**A.4.12. **
存储过程是否有引起应用程序错误的语句?
是。 MySQL 5.7 实现了 SQL 标准SIGNALRESIGNAL语句。参见第 13.6.7 节“条件处理”

**A.4.13. **
存储过程是否提供异常处理?
MySQL 根据 SQL 标准实现HANDLER定义。有关详细信息,请参见第 13.6.7.2 节“ DECLARE ... HANDLER 语句”

** A.4.14. *
MySQL 5.7 存储例程能否返回结果集?
存储过程可以,但是存储函数不能。如果在存储过程中执行普通的SELECT,则结果集将直接返回给 Client 端。您需要使用 MySQL 4.1(或更高版本)的 Client 端/服务器协议才能正常工作。这意味着,例如,在 PHP 中,您需要使用mysqliextensions 而不是旧的mysqlextensions。

**A.4.15. **
存储过程是否支持WITH RECOMPILE
不在 MySQL 5.7 中。

**A.4.16. **
是否有 MySQL 等同于在 Apache 上使用mod_plsql作为网关来直接与数据库中的存储过程进行对话?
MySQL 5.7 中没有等效项。

**A.4.17. **
我可以将数组作为 Importing 传递给存储过程吗?
不在 MySQL 5.7 中。

**A.4.18. **
我可以将游标作为IN参数传递给存储过程吗?
在 MySQL 5.7 中,游标仅在存储过程中可用。

**A.4.19. **
我可以从存储过程中将游标作为OUT参数返回吗?
在 MySQL 5.7 中,游标仅在存储过程中可用。但是,如果未在SELECT上打开游标,则结果将直接发送到 Client 端。您也可以SELECT INTO个变量。参见第 13.2.9 节“ SELECT 语句”

**A.4.20. **
我可以在存储的例程中打印出变量的值以进行调试吗?
是的,您可以在存储过程中执行此操作,但不能在存储函数中执行此操作。如果在存储过程中执行普通的SELECT,则结果集将直接返回给 Client 端。您需要使用 MySQL 4.1(或更高版本)的 Client 端/服务器协议才能正常工作。这意味着,例如,在 PHP 中,您需要使用mysqliextensions 而不是旧的mysqlextensions。

**A.4.21. **
我可以在存储过程内提交或回退事务吗?
是。但是,您不能在存储的函数中执行事务操作。

**A.4.22. **
MySQL 5.7 存储过程和函数可用于复制吗?
是的,在存储过程和函数中执行的标准操作是从 MySQL 主服务器复制到从属服务器的。 第 23.7 节“存储的程序二进制日志”中详细描述了一些限制。

**A.4.23. **
在主服务器上创建的存储过程和函数是否已复制到从属服务器?
是的,通过主服务器上的常规 DDL 语句执行的存储过程和函数的创建被复制到从服务器上,因此对象将同时存在于两个服务器上。还复制了用于存储过程和函数的ALTERDROP语句。

**A.4.24. **
如何复制存储过程和函数内部发生的操作?
MySQL 记录存储过程中发生的每个 DML 事件,并将这些单独的动作复制到从属服务器。执行存储过程的实际调用不会被复制。
更改数据的存储函数记录为函数调用,而不记录为每个函数内部发生的 DML 事件。

**A.4.25. **
将存储过程和函数与复制一起使用是否有特殊的安全要求?
是。由于从属服务器有权执行从主控二进制日志中读取的任何语句,因此存在特殊的安全性约束,以便将存储功能与复制一起使用。如果复制或二进制日志记录一般处于活动状态(出于时间点恢复的目的),则 MySQL DBA 具有两个安全选项:
任何希望创建存储功能的用户都必须被授予SUPER特权。
另外,DBA 可以将log_bin_trust_function_creators系统变量设置为 1,这使具有标准CREATE ROUTINE特权的任何人都可以创建存储的函数。

**A.4.26. **
复制存储过程和函数操作存在哪些限制?
存储过程中嵌入的不确定性(随机)或基于时间的操作可能无法正确复制。就其本质而言,随机产生的结果是不可预测的并且无法准确地再现,因此,复制到从属设备的随机操作将不会镜像在主设备上执行的操作。将存储的函数声明为DETERMINISTIC或将log_bin_trust_function_creators系统变量设置为 0 将不允许调用随机值的操作。
此外,基于时间的操作无法在从属服务器上重现,因为在存储过程中此类操作的时序无法通过用于复制的二进制日志进行重现。它仅记录 DML 事件,不考虑时序约束。
最后,在大型 DML 操作(例如批量插入)期间发生错误的非事务处理 table 可能会遇到复制问题,因为可能会从 DML 活动中部分地更新主服务器,但是由于发生错误而不会对从服务器进行更新。解决方法是使用IGNORE关键字执行函数的 DML 操作,以便忽略导致错误的主服务器上的更新,并将不会导致错误的更新复制到从属服务器上。

**A.4.27. **
以上限制是否影响 MySQL 进行时间点恢复的能力?
影响复制的相同限制确实会影响时间点恢复。

**A.4.28. **
正在采取哪些措施纠正上述限制?
您可以选择基于语句的复制或基于行的复制。原始复制实现基于基于语句的二进制日志记录。基于行的二进制日志记录解决了前面提到的限制。
也可以使用混合复制(通过使用--binlog-format=mixed启动服务器)。这种混合复制形式“知道”可以安全地使用语句级复制,还是需要行级复制。
有关更多信息,请参见第 16.2.1 节“复制格式”