标签
[begin_label:] BEGIN
[statement_list]
END [end_label]
[begin_label:] LOOP
statement_list
END LOOP [end_label]
[begin_label:] REPEAT
statement_list
UNTIL search_condition
END REPEAT [end_label]
[begin_label:] WHILE search_condition DO
statement_list
END WHILE [end_label]
-
begin ... end,loop,repeat,while允许使用标签 - 标签的规则如下:
-
begin_label后面必须跟着: -
begin_label可以不带end_label,如果end_label存在,则其必须与begin_label一样create procedure Fun0() begin end; create procedure Fun1() szn : begin end szn; create procedure Fun2() szn : begin end; -
end_label若存在,必须匹配begin_label -
标签最多可以包含16个字符
-
begin ... end
[begin_label:] BEGIN
[statement_list]
END [end_label]
-
begin ... end用于编写复合语句,其可以出现在- 存储过程
stored procedures - 函数
functions - 触发器
triggers - 事件
evnets
- 存储过程
-
begin ... end是可以嵌套的
declare
-
declare语句可以用于定义:- 本地变量
conditionshandlers- 游标
-
declare只能在begin ... end中使用,且必须位于任何其他语句之前 -
declare的顺序:- 变量和
conditions - 游标
handler
- 变量和
存储程序中的变量
-
使用
declare定义本地变量DECLARE var_name [, var_name] ... type [DEFAULT value]- 上述语句在存储程序中定义本地变量
- 可以包含
default赋予变量默认值,这个默认值可以是一个表达式 - 若无
default则变量的默认值是null - 本地变量的生命周期在定义其的
begin ... end块内
delimiter $$ create procedure Fun() begin declare a int default 10; select a; begin select a; end; begin declare a int default 20; select a; end; end $$ delimiter ; call Fun(); /* a 10 a 10 a 20 */ -
使用
set设置本地变量 -
将查询结果赋值给本地变量
-
select ... into var_list -
打开游标,使用
fetch ... into var_list
-
流程控制语句
-
mysql支持存储程序中使用if,case,iterate,leave,loop,while,repeat - 函数中支持
return - 不支持
for
case
#值匹配
CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list] ...
[ELSE statement_list]
END CASE
#条件匹配
CASE
WHEN search_condition THEN statement_list
[WHEN search_condition THEN statement_list] ...
[ELSE statement_list]
END CASE
-
case匹配失败,且不包含else子句,则会报错 - 处理
when没有匹配的情况,此时else可以包含一个空的begin ... end
delimiter $$
create procedure Fun(in v0 int, out v1 int, out v2 int)
begin
case
when v0 > 0 then
set v1 = v0 + 1;
set v2 = v0 + 2;
when v0 < 0 then
set v1 = v0 - 1;
set v2 = v0 - 2;
else
set v1 = v0;
set v2 = v0;
end case;
end $$
delimiter ;
call Fun(-1, @a0, @a1);
call Fun(1, @b0, @b1);
call Fun(0, @c0, @c1);
select @a0, @a1, @b0, @b1, @c0, @c1;
/*
@a0 @a1 @b0 @b1 @c0 @c1
-2 -3 2 3 0 0
*/
delimiter $$
create procedure Fun(in v0 int, out v1 int, out v2 int)
begin
case v0
when 1 then
set v1 = v0 + 1;
set v2 = v0 + 2;
when -1 then
set v1 = v0 - 1;
set v2 = v0 - 2;
else
set v1 = v0;
set v2 = v0;
end case;
end $$
delimiter ;
call Fun(-1, @a0, @a1);
call Fun(1, @b0, @b1);
call Fun(0, @c0, @c1);
select @a0, @a1, @b0, @b1, @c0, @c1;
/*
@a0 @a1 @b0 @b1 @c0 @c1
-2 -3 2 3 0 0
*/
delimiter $$
create procedure Fun(in v0 int)
begin
case
when v0 > 0 then
begin
end;
else
begin
end;
end case;
end $$
delimiter ;
call Fun(1);
if
IF search_condition THEN statement_list
[ELSEIF search_condition THEN statement_list] ...
[ELSE statement_list]
END IF
delimiter $$
create procedure Fun(in v0 int, out v1 int, out v2 int)
begin
if v0 > 0 then
set v1 = v0 + 1;
set v2 = v0 + 2;
elseif v0 < 0 then
set v1 = v0 - 1;
set v2 = v0 - 2;
else
set v1 = v0;
set v2 = v0;
end if;
end $$
delimiter ;
call Fun(-1, @a0, @a1);
call Fun(1, @b0, @b1);
call Fun(0, @c0, @c1);
select @a0, @a1, @b0, @b1, @c0, @c1;
/*
@a0 @a1 @b0 @b1 @c0 @c1
-2 -3 2 3 0 0
*/
iterate
ITERATE label
- 只能出现在
loop,repeat,while中,表示再次开始循环
leave
LEAVE label
- 退出具有指定标签的控制
- 可以在
begin ... end,loop,repeat,while中使用
loop
[begin_label:] LOOP
statement_list
END LOOP [end_label]
-
loop实现循环,通常通过leave来退出循环,在函数中也可以使用return来退出
delimiter $$
create procedure Fun()
begin
declare v int default 3;
szn:loop
select v;
set v = v - 1;
if v > 0 then
iterate szn;
end if;
leave szn;
end loop;
end $$
delimiter ;
call Fun();
/*
v
3
v
2
v
1
*/
drop procedure if exists Fun;
delimiter $$
create procedure Fun()
begin
declare v int default 3;
szn:loop
select v;
set v = v - 1;
end loop;
end $$
delimiter ;
call Fun();
#死循环,将一直进行输出
repeat
[begin_label:] REPEAT
statement_list
UNTIL search_condition
END REPEAT [end_label]
delimiter $$
create procedure Fun()
begin
declare v int default 3;
repeat
select v;
set v = v - 1;
until v < 0 #注意,此处不能有;
end repeat;
end $$
delimiter ;
call Fun();
/*
v
3
v
2
v
1
*/
return
RETURN expr
- 用于终止函数的执行,并将返回值返回给函数调用者
- 函数中至少要有一个
return语句 - 存储过程、触发器、事件中不应该使用
return
while
[begin_label:] WHILE search_condition DO
statement_list
END WHILE [end_label]
delimiter $$
create procedure Fun()
begin
declare v int default 3;
while v > 0 do
select v;
set v = v - 1;
end while;
end $$
delimiter ;
call Fun();
/*
v
3
v
2
v
1
*/
游标
#声明一个游标,并将其与一个select关联
DECLARE cursor_name CURSOR FOR select_statement
#打开已声明的游标
OPEN cursor_name
#获取下一行数据
FETCH [[NEXT] FROM] cursor_name INTO var_name [, var_name] ...
#关闭游标
CLOSE cursor_name
-
mysql支持在stored programs中使用游标,游标具有以下属性- Asensitive: The server may or may not make a copy of its result table
- Read only: Not updatable
- Nonscrollable: Can be traversed only in one direction and cannot skip rows
-
已打开的游标,使用
fetch来获取关联的select的下一行数据- If no more rows are available, a No Data condition occurs with SQLSTATE value
'02000'. To detect this condition, you can set up a handler for it (or for aNOT FOUNDcondition)
- If no more rows are available, a No Data condition occurs with SQLSTATE value
-
只有已经被打开的游标,才能被关闭。如果游标没有显式关闭,则会在
begin ... end块末尾自动关闭 -
服务器端游标允许在服务器端生成结果集,并只传输客户端请求的行。服务器端游标被实现为内部的临时表,当其大小小于
max_heap_table_size和tmp_table_size的最小值时,此临时表为memory table,否则是myisam table,所以对于大型结果集,使用游标可能会很慢show variables like 'max_heap_table_size' #16MB show variables like 'tmp_table_size' #39MB show variables like 'version' #8.0.17
游标使用示例
create table t(v0 int, name varchar(100));
insert into t(v0, name) values(0, "0"), (1, "1"), (2, "2"), (3, "3");
drop procedure if exists Fun;
delimiter $$
create procedure Fun(out vOut int)
begin
declare d int default false;
declare v int;
declare n varchar(100);
declare c cursor for select v0, name from t;
declare continue handler for not found set d = true;
open c;
create table if not exists tOut (name varchar(100));
truncate tOut;
set vOut = 0;
szn:while true do
fetch c into v, n;
if d then
leave szn;
end if;
if v % 2 then
set vOut = vOut + v;
insert into tOut(name) values(n);
end if;
end while;
close c;
end $$
delimiter ;
set @v = 0;
call Fun(@v);
select @v;
/*
@v
4
*/
select * from tOut;
/*
name
1
3
*/
条件(Condition) 处理(Handling)
-
stored program执行中可能会出现需要特殊处理(Handle)的条件(Condition),例如退出当前程序块或继续执行。handler可以应付如下Condition:- 普通条件,比如警告和异常
- 指定的条件,比如一个具体的错误代号。指定的条件可以命名,并且在
handler中进行引用
条件声明
DECLARE condition_name CONDITION FOR condition_value
condition_value: {
mysql_error_code
| SQLSTATE [VALUE] sqlstate_value
}
-
declare ... condition语句声明了一个错误情况,并进行命名,这个名字可以在declare ... handler中进行引用 -
上述
condition_value具有以下形式:-
mysql_error_code:整数数字,指示mysql错误码。不应该为0,因为0代表正确 -
SQLSTATE [VALUE] sqlstate_value:5个字符组成的字符串,指示mysql错误,不要使用00开头的值,因为其代表正确-
mysql_error_code与SQLSTATE [VALUE] sqlstate_value可参考 https://dev.mysql.com/doc/refman/8.0/en/server-error-reference.htmlselect * from tNotExists #error 1146 (42S02):table 'd0.tNotExists' does not exist /* 则: mysql_error_code = 1146 SQLSTATE [VALUE] sqlstate_value = 42S02 */
-
-
-
使用命名的条件,使得程序更加的清晰可读。两种条件声明示例:
drop procedure if exists Fun; delimiter $$ create procedure Fun() begin declare table_is_not_exist_0 condition for 1146; declare table_is_not_exist_1 condition for sqlstate '42S02'; end $$ delimiter ;
声明处理
DECLARE handler_action HANDLER
FOR condition_value [, condition_value] ...
statement
handler_action: {
CONTINUE
| EXIT
| UNDO
}
condition_value: {
mysql_error_code
| SQLSTATE [VALUE] sqlstate_value
| condition_name
| SQLWARNING
| NOT FOUND
| SQLEXCEPTION
}
-
declare ... handle语句声明了一个handle,用于指定处理一个或多个情况。如果其中的一个情况发生,那么指定的statement将被执行,其中statement可以是set var_name = value这样的简单语句,也可以是begin ... end这样的复合语句 -
handler_action表示statement执行后的动作,如下:-
condition:继续执行当前程序 -
exit:表示退出声明handle时所处的begin ... end语句块 -
undo:不支持
-
-
condition_value表示用于激活handle的指定条件或者是一类条件:-
mysql_error_code:mysql错误码 -
SQLSTATE [VALUE] sqlstate_value:5个字符组成的字符串,指示mysql错误 -
condition_name:声明的条件名称 -
SQLWARNING:以01开头的sqlstate的简写 -
NOT FOUND:以02开头的sqlstate的简写。在游标上下文中,如果没有跟多行可用,会触发此错误 -
SQLEXCEPTION:不以00,01,02开头的sqlstate的简写
-
-
当
Condition被触发,且没有对应的handle与之关联,则-
对于
SQLEXCEPTION:-
stored program在触发对应条件处退出,就像在此处有定义了exit的handler一样 - 如果程序是在另一个
stored program中调用,那么由调用者的handle的规则去处理
drop procedure if exists Fun; delimiter $$ create procedure Fun() begin signal sqlstate '03001'; select "szn"; end $$ delimiter ; call Fun(); #error 1644(03001): unhandled user-defined exception conditiondrop procedure if exists Fun0; drop procedure if exists Fun1; delimiter $$ create procedure Fun0() begin signal sqlstate '03001'; select "Fun0"; end $$ create procedure Fun1() begin declare continue handler for sqlexception begin end; call Fun0(); select "szn"; end $$ delimiter ; call Fun1(); /* szn --- szn */ call Fun0(); #error 1644(03001): unhandled user-defined exception condition -
-
对于
SQLWARNING,程序将继续执行,就像此处有定义了continue的handler一样drop procedure if exists Fun; delimiter $$ create procedure Fun() begin signal sqlstate '01001'; select "szn"; end $$ delimiter ; call Fun(); /* szn --- szn */ -
对于
NOT FOUND:- 如果条件是被正常触发的,则表现为
continue - 如果条件是被
signal或者resignal触发的,则表现为exit
drop procedure if exists Fun; delimiter $$ create procedure Fun() begin declare v0 int; declare c cursor for select v from t; drop table if exists t; create table t(v int); insert into t(v) values(1); open c; fetch c into v0; select v0; fetch c into v0; select "szn"; close c; end $$ delimiter ; call Fun(); /* v0 1 error 1329 (02000): no data - zero rows fetched, selectd, or processed */drop procedure if exists Fun; delimiter $$ create procedure Fun() begin signal sqlstate '02000'; select "szn"; end $$ delimiter ; call Fun(); #error1643 (02000): unhandled user-defined not found condition - 如果条件是被正常触发的,则表现为
-
-
外部
label不能在handler中使用。所以statement中,不允许使用leave或者iterate,来引用外层的labeldrop procedure if exists Fun; delimiter $$ create procedure Fun() szn : begin declare continue handler for not found begin # leave szn; 非法 # iterate szn; 非法 end; end $$ delimiter ; -
示例:
drop procedure if exists Fun; delimiter $$ create procedure Fun() begin declare table_is_not_exist_0 condition for 1146; declare continue handler for table_is_not_exist_0 begin select "Error : Table Not Found"; end; select * from t; end $$ delimiter ; call Fun(); /* 若表t存在,则输出表t的内容,否则输出Error : Table Not Found */
Signal
SIGNAL condition_value
[SET signal_information_item
[, signal_information_item] ...]
condition_value: {
SQLSTATE [VALUE] sqlstate_value
| condition_name
}
signal_information_item:
condition_information_item_name = simple_value_specification
condition_information_item_name: {
CLASS_ORIGIN
| SUBCLASS_ORIGIN
| MESSAGE_TEXT
| MYSQL_ERRNO
| CONSTRAINT_CATALOG
| CONSTRAINT_SCHEMA
| CONSTRAINT_NAME
| CATALOG_NAME
| SCHEMA_NAME
| TABLE_NAME
| COLUMN_NAME
| CURSOR_NAME
}
-
signal用于主动引发一个错误,并提供给handler、外部程序、客户端 -
signal中的condition_value指明了返回的错误,condition_value可以是以下值:-
sqlstate值,包含5个字符 - 使用
declare ... condition声明的condition的名字。此condition必须以sqlstate定义,而不能以mysql_error_code定义(参见前面的condition的两种定义方式)
-
-
signal声明语句中包含可选的多个set语句-
condition_information_item_name列表中包含了可以被set的值Item Name Definition --------- ---------- CLASS_ORIGIN VARCHAR(64) SUBCLASS_ORIGIN VARCHAR(64) CONSTRAINT_CATALOG VARCHAR(64) CONSTRAINT_SCHEMA VARCHAR(64) CONSTRAINT_NAME VARCHAR(64) CATALOG_NAME VARCHAR(64) SCHEMA_NAME VARCHAR(64) TABLE_NAME VARCHAR(64) COLUMN_NAME VARCHAR(64) CURSOR_NAME VARCHAR(64) MESSAGE_TEXT VARCHAR(128) MYSQL_ERRNO SMALLINT UNSIGNED- 以上使用的字符集是
utf8 - 以上值不允许设为
null
- 以上使用的字符集是
-
同一个变量不允许
set多次 -
simple_value_specification即被设置的变量的值,可以是-
stored procedure的参数 - 函数的参数
-
stored procedure中定义的本地变量 - 用户定义的变量
- 系统变量
- 字面量
drop procedure if exists Fun; delimiter $$ create procedure Fun(in v int) begin declare table_is_not_exist condition for sqlstate '42S02'; if v = 1 then signal sqlstate '42S03'; elseif v = 2 then signal sqlstate '42S04' set column_name = '1', table_name = '2'; else signal table_is_not_exist; end if; end $$ delimiter ; call Fun(0); #error 1644 (42S02):Unhandled user-defined exception condition call Fun(1); #error 1644 (42S03):Unhandled user-defined exception condition call Fun(2); #error 1644 (42S04):Unhandled user-defined exception condition -
-
-
signal一般在stored program中使用,但他是mysql扩展,也可以在处理程序上下文中使用signal sqlstate '42S03'; ##error 1644 (42S03):Unhandled user-defined exception condition -
signal在存储过程中使用的例子:drop procedure if exists Fun0; drop procedure if exists Fun1; drop procedure if exists Fun2; delimiter $$ create procedure Fun0() begin signal sqlstate value '42S02'; end $$ create procedure Fun1() begin declare exit handler for sqlexception begin end; signal sqlstate value '42S02'; end $$ create procedure Fun2() begin declare exit handler for sqlexception begin signal sqlstate value '99999' set message_text = 'szn'; end; signal sqlstate value '42S02'; end $$ delimiter ; call Fun0(); #error 1644(42S02): unhandled user-defined exception condition call Fun1(); #无错误输出 call Fun2(); #error 1644(99999): szndrop procedure if exists Fun; delimiter $$ create procedure Fun() begin declare exit handler for sqlstate '99999' begin select "szn"; end; declare continue handler for sqlstate '42S02' begin signal sqlstate value '99999' set message_text = 'szn'; end; signal sqlstate value '42S02'; end $$ delimiter ; call fun(); #error 1644(99999):szn -
condition_value总是一个sqlstate值,要么是直接指定,要么是通过condition间接指定。sqlstate的前两个字符指明了其类别:-
'00':表示成功,不允许指定此值 -
'01':- 表示警告
-
show warnings可显示此signal -
sqlwarning handler可以捕捉这个信号
#此类 condition_information_item_name 中值的默认值 MESSAGE_TEXT = 'Unhandled user-defined warning condition'; MYSQL_ERRNO = ER_SIGNAL_WARN -
'02':表示not found-
not found handler可以捕捉此信号 -
对游标无影响
drop table if exists t; create table t(v0 int); insert into t(v0) values(1), (2), (3); drop procedure if exists Fun; delimiter $$ create procedure Fun(out vOut int) begin declare v int; declare c cursor for select v0 from t; declare continue handler for not found begin select "szn"; end; open c; set vOut = 0; fetch c into v; set vOut = vOut + v; signal sqlstate '02000'; fetch c into v; set vOut = vOut + v; close c; end $$ delimiter ; set @v = 0; call Fun(@v); #输出szn select @v; #3 -
若此类型信号未进行捕获,则立刻结束语句块
#此类 condition_information_item_name 中值的默认值 MESSAGE_TEXT = 'Unhandled user-defined not found condition'; MYSQL_ERRNO = ER_SIGNAL_NOT_FOUND -
-
大于
'02':表示异常-
sqlexception可以捕获此信号 - 若此类型信号未进行捕获,则立刻结束语句块
#此类 condition_information_item_name 中值的默认值 MESSAGE_TEXT = 'Unhandled user-defined exception condition'; MYSQL_ERRNO = ER_SIGNAL_EXCEPTION -
-
-
在调用了
signal后- C API
-
mysql_sqlstate():返回sqlstate值 -
mysql_errno():返回MYSQL_ERROR和MESSAGE_TEXT
-
- Sql语句:
show warnings和show errors指明了MYSQL_ERROR和MESSAGE_TEXT
- C API
Resignal
RESIGNAL [condition_value]
[SET signal_information_item
[, signal_information_item] ...]
condition_value: {
SQLSTATE [VALUE] sqlstate_value
| condition_name
}
signal_information_item:
condition_information_item_name = simple_value_specification
condition_information_item_name: {
CLASS_ORIGIN
| SUBCLASS_ORIGIN
| MESSAGE_TEXT
| MYSQL_ERRNO
| CONSTRAINT_CATALOG
| CONSTRAINT_SCHEMA
| CONSTRAINT_NAME
| CATALOG_NAME
| SCHEMA_NAME
| TABLE_NAME
| COLUMN_NAME
| CURSOR_NAME
}
-
在
condition handler中,resignal传递可更改的error condition-
signal是创建error condition,而resignal是依赖已有的error condition并能进行更改
-
-
resignal和signal的condition_value及signal_information_item的规则是相同的 -
resignal的condition_value和set子句都是可选的
单独的Resignal
- 单独的
resignal意味着仅传递错误,不进行更改
drop procedure if exists Fun;
drop table t if exists;
delimiter $$
create procedure Fun()
begin
declare continue handler for sqlexception
begin
select "szn0";
resignal;
select "szn1";
end;
drop table t;
end $$
delimiter ;
call Fun();
/*
szn0
----
szn0
error 1051 (42S02):unknow table 'd0.t'
*/
show errors;
/*
Level Code Message
---- ---- -------------------
Error 1051 unknow table 'd0.t'
*/
drop table t;
#error 1051 (42S02):unknow table 'd0.t'
仅更改signal_information_item的Resignal
drop procedure if exists Fun;
drop table t if exists;
delimiter $$
create procedure Fun()
begin
declare continue handler for sqlexception
begin
select "szn";
resignal
set mysql_errno = 5,
message_text = "hello";
end;
drop table t;
end $$
delimiter ;
call Fun();
/*
szn
---
szn
error 5 (42S02):hello
*/
show errors;
/*
Level Code Message
---- ---- -------------------
Error 5 hello
*/
drop table t;
#error 1051 (42S02):unknow table 'd0.t'
更改condition_value及可选的signal_information_item的Resignal
drop procedure if exists Fun;
drop table t if exists;
delimiter $$
create procedure Fun()
begin
declare continue handler for sqlexception
begin
select "szn";
resignal sqlstate '04123'
set mysql_errno = 5, #可选
message_text = "hello"; #可选
end;
drop table t;
end $$
delimiter ;
call Fun();
/*
szn
---
szn
error 5 (04123):hello
*/
show errors;
/*
Level Code Message
---- ---- -------------------
Error 1051 unknow table 'd0.t'
Error 5 hello
*/
drop table t;
#error 1051 (42S02):unknow table 'd0.t'
Handler的范围规则
stored program可以包含多个handler,当特定的条件在program中发生时,进行调用。hanlder的适用性取决于其自身定义的位置以及其关联的condition:
-
begin ... end中declare的handler,其范围只适用于begin ... end块剩余的sql语句。如果handler自身触发了condition,其自身无法处理这个condition,并且begin ... end块内的任何其他handler也无法处理BEGIN -- outer block DECLARE EXIT HANDLER FOR ...; -- handler H1 DECLARE EXIT HANDLER FOR ...; -- handler H2 stmt1; stmt2; END; #H1和H2适用于由stmt1和stmt2触发的condition,但是无论是H1还是H2都无法处理在H1和H2内部触发的condition -
handler的仅适用于declare其本身的begin ... end块内,无法处理外部引发的conditionBEGIN -- outer block BEGIN -- inner block DECLARE EXIT HANDLER FOR ...; -- handler H1 stmt1; END; stmt2; END; #在上述例子中,H1适用于由stmt1引发的condition,而不适用于stmt2引发的condition -
handler是否被触发,不仅取决于其自身声明的位置和条件,还受当前块中的其他handler影响。当condition被触发,服务器将搜索当前begin ... end块中适用的handler,如果当前没有合适的handler,服务器将继续搜索外部块中的handler,当服务器在指定的块中找到了一个或者多个可用的handler,将按照如下优先级进行选择- 最局部的且符合
condition的handler优于外部的handler - 关联了
mysql error code的handler - 关联了
sqlstate value的handler - 关联了
sqlexception的handler - 关联了
sqlwarning、not found的handler
- 最局部的且符合
-
同时具有多个可用的且优先级相同的
handler是可能的。比如说一条语句可能同时触发多个general warning并且对应的handler都存在。此时无法保证哪个handler会被触发
Demo
drop procedure if exists Fun0;
drop procedure if exists Fun1;
drop procedure if exists Fun2;
drop procedure if exists Fun3;
drop table if exists t;
delimiter $$
#Fun0
create procedure Fun0()
begin
declare continue handler for sqlexception
select "sql exception";
declare continue handler for sqlstate '42S02'
select "sql state";
drop table t;
end $$
#Fun1
create procedure Fun1()
begin
declare continue handler for sqlstate '42S02'
select "sql state";
begin
declare continue handler for sqlexception
select "sql exception";
drop table t;
end;
end $$
#Fun2
create procedure Fun2()
begin
declare continue handler for sqlstate '42S02'
select "sql state";
begin
declare continue handler for sqlexception
select "sql exception";
end;
drop table t;
end $$
#Fun3
create procedure Fun3()
begin
begin
declare continue handler for sqlstate '42S02'
select "sql state";
declare continue handler for sqlexception
select "sql exception";
end;
drop table t;
end $$
delimiter ;
call Fun0();
/*
sql state
---------
sql state
*/
call Fun1();
/*
sql exception
-------------
sql exception
*/
call Fun2();
/*
sql state
---------
sql state
*/
call Fun3();
#error 1051 (42S02): unknow table 'd0.t'
Condition Handling and OUT or INOUT Parameters
-
如果存储过程因为一个没有处理的
exception而退出,被更改的out和inout参数不会被传递给调用者drop procedure if exists Fun; delimiter $$ create procedure Fun(out v0 int, inout v1 int) begin set v0 = 1; set v1 = 2; select "Inner", v0, v1; signal sqlstate '04001'; end $$ delimiter ; call Fun(@a, @b); /* Inner v0 v1 ------------- Inner 1 2 */ select @a, @b; /* @a @b ------------ null null */
参考
https://dev.mysql.com/doc/refman/8.0/en/sql-compound-statements.html












网友评论