我描述一下现在出现的问题。
存储过程 A,B.
A大致内容如下:DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
start transaction;
调用存储过程B
commit;
B存储过程比较简单就是对一个传入的长字符串进行截取,然后在插入数据库。(不包含start transaction;和commit;)
在一般情况下,无论是A还是B中出现异常都能进行回滚到存储过程A执行前的状态。
但是我最近发现存储过程B传入字符串为“”时,无法回滚。存储过程B的代码如下:
declare ilen int;
declare iTollen int;declare dSevMA double;
declare dSevOA double;
Set ilen = locate('|',strSevHowToPay)-1;
Set iTollen = Length(strSevHowToPay) - ilen -1;
Set dSevMA = left(strSevHowToPay,ilen);
Set strSevHowToPay = substring(strSevHowToPay,iLen+2,iTollen);Set ilen = locate('|',strSevHowToPay)-1;
Set iTollen = Length(strSevHowToPay) - ilen -1;
Set dSevOA = left(strSevHowToPay,ilen);
Set strSevHowToPay = substring(strSevHowToPay,iLen+2,iTollen);
strSevHowToPay为传入的长字符串,当它为“”时,出现的异常。
存储过程A中DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK; 无法进行回滚。这是怎么回事?
难道存储过程A中DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK; 无法对存储过程B中出现的异常进行回滚?是否需要在存储过程B中添加DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK。
存储过程 A,B.
A大致内容如下:DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
start transaction;
调用存储过程B
commit;
B存储过程比较简单就是对一个传入的长字符串进行截取,然后在插入数据库。(不包含start transaction;和commit;)
在一般情况下,无论是A还是B中出现异常都能进行回滚到存储过程A执行前的状态。
但是我最近发现存储过程B传入字符串为“”时,无法回滚。存储过程B的代码如下:
declare ilen int;
declare iTollen int;declare dSevMA double;
declare dSevOA double;
Set ilen = locate('|',strSevHowToPay)-1;
Set iTollen = Length(strSevHowToPay) - ilen -1;
Set dSevMA = left(strSevHowToPay,ilen);
Set strSevHowToPay = substring(strSevHowToPay,iLen+2,iTollen);Set ilen = locate('|',strSevHowToPay)-1;
Set iTollen = Length(strSevHowToPay) - ilen -1;
Set dSevOA = left(strSevHowToPay,ilen);
Set strSevHowToPay = substring(strSevHowToPay,iLen+2,iTollen);
strSevHowToPay为传入的长字符串,当它为“”时,出现的异常。
存储过程A中DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK; 无法进行回滚。这是怎么回事?
难道存储过程A中DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK; 无法对存储过程B中出现的异常进行回滚?是否需要在存储过程B中添加DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK。
但是无法对在调用存储过程B之前的存储过程A所执行的语句进行回滚如果想在意在存储过程中进行回滚应当如何处理
?、
我将我自己的测试例子发上来,大家能不能帮我看看表T1
ID Name
--------------- -------------
01 Lee存储过程Proc1
BEGIN
#Routine body goes here...
DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK; set autocommit = 0; start transaction;
delete from t1;
insert into t1 values('02','1ss');
call Proc2(A); update t1 Set name = '3ss';
commit;
END
存储过程Proc2
BEGIN
#Routine body goes here...
declare ilen int;
declare iTollen int;
declare dSevMA double;
Set ilen = locate('|','')-1;
Set iTollen = Length('') - ilen -1;
Set dSevMA = left('',ilen);
update t1 Set name = '12';
END
Set @a = 0;
Call Proc1(@a);后会提示Proc2 中存在错误。
同时数据库中T1表格没有发生变化。但是如果在执行其他语句。T1表中值就会变为
ID Name
--------------- -------------
02 1ss
就是说 对于Proc2中发生的错误,Proc1中无法进行回滚。这样应当如何处理比较好?我现在对于这种情况,是在提示后执行存储过程Proc1失败后,马上执行RollBack!但是这样就不在一个存储过程中,是否有影响?
delete from t1;
insert into t1 values('02','1ss');nextproc:begin
DECLARE IS_ERROR INTEGER DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET IS_ERROR=1;
call Proc2(A);
if is_error=1
rollback;
end if;
end nextproc;
update t1 Set name = '3ss';commit;
END
还是不行。 同时:我将Proc2中的代码转移到Proc1中:
BEGIN
#Routine body goes here...
declare ilen int;
declare iTollen int;
declare dSevMA double; DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK; set autocommit = 0; start transaction;
delete from t1;
insert into t1 values('2','D');
nextproc:begin
DECLARE IS_ERROR INTEGER DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET IS_ERROR=1;
Set ilen = locate('|','')-1;
Set iTollen = Length('') - ilen -1;
Set dSevMA = left('',ilen); if is_error=1 then
rollback;
end if;
end nextproc;
update t1 Set name = '3';
commit;
END
感觉问题的关键是SQLEXCEPTION 不包含这个存储过程中发生的错误!
说明出问题不在于是否嵌套调用存储过程关键是SQLEXCEPTION 不包含这个存储过程中发生的错误!
不能对发生的错误进行处理
NOT DETERMINISTIC
SQL SECURITY DEFINER
COMMENT ''
BEGIN
declare ilen int;
declare iTollen int; declare dSevMA double;
Set ilen = locate('|','')-1;
Set iTollen = Length('') - ilen -1;
Set dSevMA = left('',ilen);
END;call new_proc() -- 是成功的, 怎么会产生异常呢?还是你要让它抛出异常?
我这边提示这句有错!
数据截断出错了