对存储程序的限制
这些限制适用于存储的对象中描述的功能。
此处指出的某些限制适用于所有存储的例程。也就是存储过程和存储函数。也有一些特定于存储功能的限制,而不是特定于存储过程的限制。
存储功能的限制也适用于触发器。还有一些特定于触发器的限制。
存储过程的限制也适用于DO
Event Scheduler事件定义的子句。对于事件也有一些限制。
存储例程中不允许使用SQL语句
存储的例程不能包含任意SQL语句。以下语句是不允许的:
- 锁定语句
LOCK TABLES
和UNLOCK TABLES
。 ALTER VIEW
。LOAD DATA
和LOAD TABLE
。- SQL语句制备(
PREPARE
,EXECUTE
,DEALLOCATE PREPARE
)可以在存储过程中使用,但没有存储功能或触发器。因此,存储的函数和触发器不能使用动态SQL(将语句构造为字符串然后执行它们)。 - 通常,在存储程序中也不允许使用SQL预准备语句中不允许的语句。有关支持作为预备语句的语句列表,例外的是
SIGNAL
,RESIGNAL
,和GET DIAGNOSTICS
,这是不容许的作为准备语句,但被允许在存储的程序。 - 由于局部变量仅在存储程序执行期间才在范围内,因此在存储程序内创建的准备好的语句中不允许引用它们。准备的语句作用域是当前会话,而不是存储的程序,因此该语句可以在程序结束后执行,此时变量将不再在作用域内。例如,不能用作预备语句。此限制也适用于存储过程和函数参数。请参见“ PREPARE语句”。
SELECT ... INTO local_var
- 在所有存储的程序(存储的过程和函数,触发器和事件)中,解析器将其
BEGIN[WORK]
视为BEGIN ... END
块的开始。要在这种情况下开始交易,请START TRANSACTION
改用。
存储功能的限制
存储的函数中不允许以下附加语句或操作。它们在存储过程中是允许的,但从存储函数或触发器中调用的存储过程除外。例如,如果FLUSH
在存储过程中使用,则不能从存储函数或触发器中调用该存储过程。
- 执行显式或隐式提交或回滚的语句。SQL标准不需要支持这些语句,该标准指出每个DBMS供应商都可以决定是否允许它们。
- 返回结果集的语句。这包括
SELECT
不具有的声明条款等语句,如,和。函数可以使用或使用游标和语句来处理结果集。请参见“ SELECT ... INTO语句”和“游标”。INTO var_list
SHOW
EXPLAIN
CHECK TABLE
SELECT ... INTO var_list
FETCH
FLUSH
陈述。- 不能递归使用存储的函数。
- 存储的函数或触发器无法修改调用该函数或触发器的语句已在使用(用于读取或写入)的表。
- 如果在存储的函数中使用不同的别名多次引用临时表,即使引用在函数内的不同语句中发生,也会发生错误。
Can't reopen table:'tbl_name'
HANDLER ... READ
调用存储函数的语句可能会导致复制错误,因此是不允许的。
触发器限制
对于触发器,以下附加限制适用:
- 触发器不能通过外键动作激活。
- 使用基于行的复制时,从服务器上的触发器不会被主服务器上的语句激活。使用基于语句的复制时,将激活从属服务器上的触发器。有关更多信息,请参见“触发器语法”。
RETURN
触发器不允许返回该值的触发器中不允许使用该语句。要立即退出触发器,请使用以下LEAVE
语句。- 不允许在
mysql
数据库中的表上使用触发器。他们也没有被允许上INFORMATION_SCHEMA
或performance_schema
表。这些表实际上是视图,并且视图上不允许使用触发器。 - 触发器缓存不会检测基础对象的元数据何时更改。如果触发器使用表,并且自将触发器加载到缓存以来表已更改,则触发器将使用过时的元数据进行操作。
存储例程中的名称冲突
相同的标识符可能用于例程参数,局部变量和表列。同样,可以在嵌套块中使用相同的局部变量名称。例如:
CREATE PROCEDURE p (i INT)BEGIN DECLARE i INTDEFAULT 0;SELECT iFROM t;BEGIN DECLARE i INTDEFAULT 1;SELECT iFROM t;END ;END ;
在这种情况下,标识符不明确,并且适用以下优先级规则:
- 局部变量优先于常规参数或表列。
- 例程参数优先于表列。
- 内部块中的局部变量优先于外部块中的局部变量。
变量优先于表列的行为是非标准的。
复制注意事项
使用存储的例程可能会导致复制问题。在“存储的程序二进制日志记录”中将进一步讨论此问题。
该选项适用于表,视图和触发器。它不适用于存储过程和功能或事件。要过滤对后一个对象操作的语句,请使用一个或多个选项。--replicate-wild-do-table=db_name.tbl_name
--replicate-*-db
调试注意事项
没有存储的例行调试功能。
SQL:2003标准中不受支持的语法
MySQL存储的例程语法基于SQL:2003标准。当前不支持该标准中的以下各项:
UNDO
处理程序FOR
循环
存储的常规并发注意事项
为了防止会话之间的交互问题,当客户端发出一条语句时,服务器使用例程快照和触发器来执行该语句。即,服务器计算在语句执行期间可能使用的过程,函数和触发器的列表,加载它们,然后继续执行该语句。语句执行时,看不到其他会话对例程执行的更改。
为了获得最大的并发性,存储的函数应将其副作用降到最低。特别是,更新存储功能中的表可以减少对该表的并发操作。存储的函数在执行之前获取表锁,以避免二进制日志由于语句执行顺序和语句出现在日志中的顺序不匹配而导致不一致。使用基于语句的二进制日志记录时,将记录调用函数的语句,而不是记录在函数内执行的语句。因此,更新相同基础表的存储函数不会并行执行。相反,存储过程不获取表级锁。在存储过程中执行的所有语句都被写入二进制日志,即使对于基于语句的二进制日志记录也是如此。看到“存储的程序二进制日志记录”。
事件计划程序限制
以下限制特定于事件计划程序:
- 事件名称以不区分大小写的方式处理。例如,在同一个数据库中不能有两个事件,它们的名称分别为
anEvent
和AnEvent
。 - 如果事件名称是通过变量指定的,则不能在存储程序中创建,更改或删除事件。事件也可能不会创建,更改或删除存储的例程或触发器。
- 声明
LOCK TABLES
生效时,禁止在事件上使用DDL声明。 - 使用间隔事件时序
YEAR
,QUARTER
,MONTH
,并YEAR_MONTH
在几个月解决;那些使用其他间隔的时间将在几秒钟内解决。无法使计划在同一秒发生的事件以给定顺序执行。此外,由于四舍五入,线程应用程序的性质以及创建事件和表示其执行需要非零时间长度的事实,事件可能会延迟多达1或2秒。但是,INFORMATION_SCHEMA.EVENTS
表中显示的时间LAST_EXECUTED
列始终准确到实际事件执行时间的一秒以内。(另请参见Bug#16522。) - 事件主体中包含的语句的每次执行都在新的连接中进行;因此,这些语句在服务器上的语句数给定的用户会话没有影响,如
Com_select
和Com_insert
由显示SHOW STATUS
。但是,此类计数会在全局范围内更新。错误16422) - 事件的支持时间不晚于Unix Epoch的结束。这大约是2038年的年初。事件计划程序明确不允许这样的日期。错误16396)
- 不支持
ON SCHEDULE
在CREATE EVENT
和ALTER EVENT
语句的子句中引用存储的函数,用户定义的函数和表。不允许使用此类参考。(有关更多信息,请参见Bug#22830。)
NDB群集中存储的例程和触发器。使用NDB
存储引擎的表都支持存储过程,存储函数和触发器。但是,请记住,它们不会在充当群集SQL节点的MySQL服务器之间自动传播。这是因为存储的例程和触发器定义是mysql
使用InnoDB
表存储在系统数据库的表中的,这些表未在群集节点之间复制。
必须通过在参与要使用存储例程或触发器的群集的每个MySQL服务器上运行相应的,或语句CREATE PROCEDURE
,来重新创建与MySQL群集表交互的任何存储例程或触发器。同样,必须在所有Cluster SQL节点上显式地执行对现有存储例程或触发器的任何更改,并在每个访问群集的MySQL Server上使用适当的或语句。CREATE FUNCTION
CREATE TRIGGER
ALTER
DROP
警告难道不是试图解决只是通过转换所描述的任何问题,
mysql
数据库表使用的NDB
存储引擎。不支持更改mysql
数据库中的系统表,并且很可能产生不良结果。