这些限制适用于 第 27 章,存储对象 中描述的功能。These restrictions apply to the features described in Chapter 27, Stored Objects.
这里提到的一些限制适用于所有存储例程;也就是说,既适用于存储过程,也适用于存储函数。还有一些仅适用于存储函数的限制,而不适用于存储过程。Some of the restrictions noted here apply to all stored routines; that is, both to stored procedures and stored functions. There are also some restrictions specific to stored functions but not to stored procedures.
存储函数的限制同样适用于触发器。还有一些仅适用于触发器的限制。The restrictions for stored functions also apply to triggers. There are also some restrictions specific to triggers.
存储过程的限制同样适用于事件调度器事件定义中的 DO 子句。事件还有一些 特定的限制。The restrictions for stored procedures also apply to the
DO clause of Event Scheduler event
definitions. There are also some
restrictions
specific to events.
存储例程不能包含任意 SQL 语句。以下语句是不允许的:Stored routines cannot contain arbitrary SQL statements. The following statements are not permitted:
锁定语句
LOCK TABLES和UNLOCK TABLES。The locking statementsLOCK TABLESandUNLOCK TABLES.SQL 预处理语句(
PREPARE、EXECUTE、DEALLOCATE PREPARE)可以在存储过程(stored procedures)中使用,但不能在存储函数(stored functions)或触发器(triggers)中使用。因此,存储函数和触发器不能使用动态 SQL(动态构建语句作为字符串然后执行的 SQL)。SQL prepared statements (PREPARE,EXECUTE,DEALLOCATE PREPARE) can be used in stored procedures, but not in stored functions or triggers. Thus, stored functions and triggers cannot use dynamic SQL (where you construct statements as strings and then execute them).通常,SQL 预处理语句中不允许的语句,在存储程序中也不允许。有关支持作为预处理语句的语句列表,请参见 第 15.5 节,“预处理语句”。例外情况是
SIGNAL、RESIGNAL以及GET DIAGNOSTICS,它们不允许作为预处理语句,但在存储程序中允许使用。Generally, statements not permitted in SQL prepared statements are also not permitted in stored programs. For a list of statements supported as prepared statements, see Section 15.5, “Prepared Statements”. Exceptions areSIGNAL,RESIGNAL, andGET DIAGNOSTICS, which are not permissible as prepared statements but are permitted in stored programs.由于局部变量只在存储程序执行期间有效,因此在存储程序中创建的预处理语句中不允许引用它们。预处理语句的作用域是当前会话,而不是存储程序,因此语句可能在程序结束后执行,届时变量将不再有效。例如,
SELECT ... INTO local_var不能作为预处理语句使用。这一限制同样适用于存储过程和函数的参数。参见 第 15.5.1 节,“PREPARE 语句”。Because local variables are in scope only during stored program execution, references to them are not permitted in prepared statements created within a stored program. Prepared statement scope is the current session, not the stored program, so the statement could be executed after the program ends, at which point the variables would no longer be in scope. For example,SELECT ... INTOcannot be used as a prepared statement. This restriction also applies to stored procedure and function parameters. See Section 15.5.1, “PREPARE Statement”.local_var在所有存储程序(存储过程和函数、触发器以及事件)中,解析器将
BEGIN [WORK]视为BEGIN ... END块的开始。Within all stored programs (stored procedures and functions, triggers, and events), the parser treatsBEGIN [WORK]as the beginning of aBEGIN ... ENDblock.要在存储过程或事件中开始事务,请使用
START TRANSACTION。To begin a transaction within a stored procedure or event, useSTART TRANSACTIONinstead.START TRANSACTION不能在存储函数或触发器中使用。START TRANSACTIONcannot be used within a stored function or trigger.
在存储函数中不允许使用以下附加语句或操作。它们在存储过程内是允许的,但存储过程如果从存储函数或触发器中调用,则不允许。例如,如果在存储过程中使用 FLUSH,则该存储过程不能从存储函数或触发器中调用。The following additional statements or operations are not
permitted within stored functions. They are permitted within
stored procedures, except stored procedures that are invoked
from within a stored function or trigger. For example, if you
use FLUSH in a stored procedure,
that stored procedure cannot be called from a stored function or
trigger.
执行显式或隐式提交或回滚的语句。这些语句的支持不是 SQL 标准所要求的,SQL 标准规定每个数据库管理系统供应商可以自行决定是否允许它们。Statements that perform explicit or implicit commit or rollback. Support for these statements is not required by the SQL standard, which states that each DBMS vendor may decide whether to permit them.
返回结果集的语句。这包括没有
SELECT子句的INTO var_list语句,以及其他语句,如SHOW、EXPLAIN和CHECK TABLE。函数可以通过SELECT ... INTO var_list或使用游标和FETCH语句来处理结果集。参见 第 15.2.13.1 节,“SELECT ... INTO 语句” 和 第 15.6.6 节,“游标”。Statements that return a result set. This includesSELECTstatements that do not have anINTOclause and other statements such asvar_listSHOW,EXPLAIN, andCHECK TABLE. A function can process a result set either withSELECT ... INTOor by using a cursor andvar_listFETCHstatements. See Section 15.2.13.1, “SELECT ... INTO Statement”, and Section 15.6.6, “Cursors”.存储函数不能递归使用。Stored functions cannot be used recursively.
存储函数或触发器不能修改已经被调用此函数或触发器的语句用于读取或写入的表。A stored function or trigger cannot modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger.
如果在存储函数中以不同的别名多次引用临时表,即使这些引用出现在函数中的不同语句中,也会出现
Can't reopen table: 'tbl_name'错误。If you refer to a temporary table multiple times in a stored function under different aliases, aCan't reopen table: 'error occurs, even if the references occur in different statements within the function.tbl_name'HANDLER ... READ语句调用存储函数可能导致复制错误,因此不允许使用。HANDLER ... READstatements that invoke stored functions can cause replication errors and are disallowed.
对于触发器,适用以下附加限制:For triggers, the following additional restrictions apply:
触发器不会被外键操作触发。Triggers are not activated by foreign key actions.
在使用基于行的复制时,源端的语句不会激活副本上的触发器。在使用基于语句的复制时,副本上的触发器会被激活。有关更多信息,请参见第 19.5.1.36 节,“复制与触发器”。When using row-based replication, triggers on the replica are not activated by statements originating on the source. The triggers on the replica are activated when using statement-based replication. For more information, see Section 19.5.1.36, “Replication and Triggers”.
触发器中不允许使用
RETURN语句,触发器不能返回值。要立即退出触发器,请使用LEAVE语句。TheRETURNstatement is not permitted in triggers, which cannot return a value. To exit a trigger immediately, use theLEAVEstatement.在
mysql数据库中的表上不允许使用触发器。INFORMATION_SCHEMA或performance_schema表上也不允许使用触发器。这些表实际上是视图,而视图上不允许使用触发器。Triggers are not permitted on tables in themysqldatabase. Nor are they permitted onINFORMATION_SCHEMAorperformance_schematables. Those tables are actually views and triggers are not permitted on views.触发器缓存无法检测底层对象的元数据何时发生变化。如果一个触发器使用了某个表,而该表在触发器加载到缓存之后发生了变化,那么触发器将使用过时的元数据进行操作。The trigger cache does not detect when metadata of the underlying objects has changed. If a trigger uses a table and the table has changed since the trigger was loaded into the cache, the trigger operates using the outdated metadata.
同一个标识符可能被用于例程参数、局部变量和表列。同时,同一个局部变量名可以在嵌套块中使用。例如:The same identifier might be used for a routine parameter, a local variable, and a table column. Also, the same local variable name can be used in nested blocks. For example:
CREATE PROCEDURE p (i INT)
BEGIN
DECLARE i INT DEFAULT 0;
SELECT i FROM t;
BEGIN
DECLARE i INT DEFAULT 1;
SELECT i FROM t;
END;
END;
在这种情况下,标识符是模糊的,并且适用以下优先级规则:In such cases, the identifier is ambiguous and the following precedence rules apply:
局部变量优先于例程参数或表列。A local variable takes precedence over a routine parameter or table column.
例程参数优先于表列。A routine parameter takes precedence over a table column.
内部块中的局部变量优先于外部块中的局部变量。A local variable in an inner block takes precedence over a local variable in an outer block.
变量优先于表列的行为是不标准的。The behavior that variables take precedence over table columns is nonstandard.
使用存储例程可能会导致复制问题。此问题在第 27.7 节,“存储程序二进制日志记录”中有进一步讨论。Use of stored routines can cause replication problems. This issue is discussed further in Section 27.7, “Stored Program Binary Logging”.
--replicate-wild-do-table= 选项适用于表、视图和触发器。不适用于存储过程和函数,或事件。要过滤操作后者对象的语句,请使用一个或多个 db_name.tbl_name--replicate-*-db 选项。The
--replicate-wild-do-table=
option applies to tables, views, and triggers. It does not apply
to stored procedures and functions, or events. To filter
statements operating on the latter objects, use one or more of
the db_name.tbl_name--replicate-*-db options.
MySQL 存储例程语法基于 SQL:2003 标准。该标准中以下项目当前不受支持:The MySQL stored routine syntax is based on the SQL:2003 standard. The following items from that standard are not currently supported:
UNDO处理程序UNDOhandlersFOR循环FORloops
为了防止会话之间的交互问题,当客户端发出语句时,服务器会使用可用于执行该语句的例程和触发器的快照。也就是说,服务器会计算在语句执行期间可能使用的存储过程、函数和触发器的列表,加载它们,然后继续执行该语句。在语句执行期间,它不会看到其他会话对例程所做的更改。To prevent problems of interaction between sessions, when a client issues a statement, the server uses a snapshot of routines and triggers available for execution of the statement. That is, the server calculates a list of procedures, functions, and triggers that may be used during execution of the statement, loads them, and then proceeds to execute the statement. While the statement executes, it does not see changes to routines performed by other sessions.
为了实现最大并发,存储函数应尽量减少其副作用;特别是,在存储函数中更新表可能会减少对该表的并发操作。存储函数在执行之前会获取表锁,以避免由于语句执行顺序与它们出现在日志中的顺序不一致而导致的二进制日志不一致。当使用基于语句的二进制日志记录时,调用函数的语句会被记录,而不是函数内部执行的语句。因此,更新相同底层表的存储函数不会并行执行。相比之下,存储过程不会获取表级锁。即使是基于语句的二进制日志,存储过程执行的所有语句也会被写入二进制日志。参见第 27.7 节,“存储程序二进制日志记录”。For maximum concurrency, stored functions should minimize their side-effects; in particular, updating a table within a stored function can reduce concurrent operations on that table. A stored function acquires table locks before executing, to avoid inconsistency in the binary log due to mismatch of the order in which statements execute and when they appear in the log. When statement-based binary logging is used, statements that invoke a function are recorded rather than the statements executed within the function. Consequently, stored functions that update the same underlying tables do not execute in parallel. In contrast, stored procedures do not acquire table-level locks. All statements executed within stored procedures are written to the binary log, even for statement-based binary logging. See Section 27.7, “Stored Program Binary Logging”.
以下限制是针对事件调度器的特定限制:The following limitations are specific to the Event Scheduler:
事件名称不区分大小写。例如,在同一个数据库中,你不能同时拥有名为
anEvent和AnEvent的两个事件。Event names are handled in case-insensitive fashion. For example, you cannot have two events in the same database with the namesanEventandAnEvent.不能从存储程序中创建事件。如果事件名称是通过变量指定的,则不能从存储程序中修改或删除事件。事件也不能创建、修改或删除存储例程或触发器。An event may not be created from within a stored program. An event may not be altered, or dropped from within a stored program, if the event name is specified by means of a variable. An event also may not create, alter, or drop stored routines or triggers.
当
LOCK TABLES语句生效时,禁止对事件执行 DDL 语句。DDL statements on events are prohibited while aLOCK TABLESstatement is in effect.使用间隔
YEAR、QUARTER、MONTH和YEAR_MONTH的事件时间以月为单位解析;使用任何其他间隔的事件以秒为单位解析。无法保证在同一秒计划执行的事件按特定顺序执行。此外——由于四舍五入、线程应用程序的特性以及创建事件和发出执行信号需要非零长度时间——事件可能延迟 1 到 2 秒。然而,Information SchemaEVENTS表的LAST_EXECUTED列显示的时间始终与实际事件执行时间的误差在一秒以内。(另见 Bug #16522。)Event timings using the intervalsYEAR,QUARTER,MONTH, andYEAR_MONTHare resolved in months; those using any other interval are resolved in seconds. There is no way to cause events scheduled to occur at the same second to execute in a given order. In addition—due to rounding, the nature of threaded applications, and the fact that a nonzero length of time is required to create events and to signal their execution—events may be delayed by as much as 1 or 2 seconds. However, the time shown in the Information SchemaEVENTStable'sLAST_EXECUTEDcolumn is always accurate to within one second of the actual event execution time. (See also Bug #16522.)事件主体中包含的每条语句的每次执行都发生在一个新的连接中;因此,这些语句不会影响服务器上特定用户会话中的语句计数,例如通过
SHOW STATUS显示的Com_select和Com_insert。然而,这些计数确实会在全局范围内更新。(Bug #16422)Each execution of the statements contained in the body of an event takes place in a new connection; thus, these statements have no effect in a given user session on the server's statement counts such asCom_selectandCom_insertthat are displayed bySHOW STATUS. However, such counts are updated in the global scope. (Bug #16422)事件不支持晚于 Unix 纪元结束的时间;大约是 2038 年年初。事件调度程序明确不允许此类日期。(Bug #16396)Events do not support times later than the end of the Unix Epoch; this is approximately the beginning of the year 2038. Such dates are specifically not permitted by the Event Scheduler. (Bug #16396)
在
CREATE EVENT和ALTER EVENT语句的ON SCHEDULE子句中,不支持对存储函数、可加载函数和表的引用。不允许使用此类引用。(有关更多信息,请参见 Bug #22830。)References to stored functions, loadable functions, and tables in theON SCHEDULEclauses ofCREATE EVENTandALTER EVENTstatements are not supported. These sorts of references are not permitted. (See Bug #22830 for more information.)
While stored procedures, stored functions, triggers, and
scheduled events are all supported by tables using the
NDB storage engine, you must keep
in mind that these do 在多线程系统中 propagate
automatically between MySQL Servers acting as Cluster SQL nodes.
This is because stored routine and trigger definitions are
stored in tables in the mysql system database
using InnoDB tables, which are not copied
between Cluster nodes.While stored procedures, stored functions, triggers, and
scheduled events are all supported by tables using the
NDB storage engine, you must keep
in mind that these do not propagate
automatically between MySQL Servers acting as Cluster SQL nodes.
This is because stored routine and trigger definitions are
stored in tables in the mysql system database
using InnoDB tables, which are not copied
between Cluster nodes.
任何与 MySQL Cluster 表交互的存储例程或触发器都必须通过在每个希望使用该存储例程或触发器的 MySQL 服务器上运行相应的 CREATE PROCEDURE、CREATE FUNCTION 或 CREATE TRIGGER 语句来重新创建。同样,对现有存储例程或触发器的任何更改必须在所有 Cluster SQL 节点上明确执行,使用每个访问集群的 MySQL 服务器上的相应 ALTER 或 DROP 语句。Any stored routine or trigger that interacts with MySQL Cluster
tables must be re-created by running the appropriate
CREATE PROCEDURE,
CREATE FUNCTION, or
CREATE TRIGGER statements on each
MySQL Server that participates in the cluster where you wish to
use the stored routine or trigger. Similarly, any changes to
existing stored routines or triggers must be carried out
explicitly on all Cluster SQL nodes, using the appropriate
ALTER or DROP statements
on each MySQL Server accessing the cluster.
执行在多线程系统中 attempt to work around the issue
just described by converting any mysql
database tables to use the NDB
storage engine. Altering the system tables in the
mysql database is not supported
and is very likely to produce undesirable results.Do not attempt to work around the issue
just described by converting any mysql
database tables to use the NDB
storage engine. Altering the system tables in the
mysql database is not supported
and is very likely to produce undesirable results.