mysql存储过程之WHILE循环,LOOP循环以及REPEAT循环
在MySQL存储过程的语句中有三个标准的循环⽅式:WHILE循环,LOOP循环以及REPEAT循环。还有⼀种⾮标准的循环⽅式:GOTO,不过这种循环⽅式最好别⽤,很容易引起程序的混乱,在这⾥就不错具体介绍了。
这⼏个循环语句的格式如下:
WHILE……DO……END WHILE
REPEAT……UNTIL END REPEAT
LOOP……END LOOP
GOTO
下⾯⾸先使⽤第⼀种循环编写⼀个例⼦。
mysql> create procedure pro10()
-> begin
-> declare i int;
-> set i=0;
-> while i<5 do
->    insert into t1(filed) values(i);
->    set i=i+1;
-> end while;
-> end;//
Query OK, 0 rows affected (0.00 sec)
在这个例⼦中,INSERT和SET语句在WHILE和END WHILE之间,当变量i⼤于等于5的时候就退出循环。使⽤set i=0;语句是为了防⽌⼀个常见的错误,如果没有初始化,i默认变量值为NULL,⽽NULL和任何值操作的结果都是NULL。
执⾏⼀下这个存储过程并产看⼀下执⾏结果:
mysql> delete from t1//
Query OK, 0 rows affected (0.00 sec)
mysql> call pro10()//
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1//
+——-+
| filed |
+——-+
|    0 |
|    1 |
|    2 |
|    3 |
|    4 |
+——-+
5 rows in set (0.00 sec)
编写xml
以上就是执⾏结果,有5⾏数据插⼊到数据库中,证明存储过程编写正确⽆误^_^。
再来看⼀下第⼆个循环控制指令 REPEAT……END REPEAT。使⽤REPEAT循环控制语句编写下⾯这个存储过程:
mysql> create procedure pro11()
-> begin
-> declare i int default 0;
-> repeat
->    insert into t1(filed) values(i);
->    set i=i+1;
->    until i>=5
-> end repeat;
-> end;//
Query OK, 0 rows affected (0.00 sec)
这个REPEAT循环的功能和前⾯WHILE循环⼀样,区别在于它的执⾏后检查是否满⾜循环条件(until i>=5),⽽WHILE则是执⾏前检查(while i<5 do)。
不过要注意until i>=5后⾯不要加分号,如果加分号,就是提⽰语法错误。
编写完成后,调⽤⼀下这个存储过程,并查看结果:
mysql> delete from t1//
Query OK, 5 rows affected (0.00 sec)
mysql> call pro11()//
Query OK, 1 row affected (0.00 sec) #虽然在这⾥显⽰只有⼀⾏数据受到影响,但是下⾯选择数据的话,还是插⼊了5⾏数据。
mysql> select * from t1//
+——-+
| filed |
+——-+
|    0 |
|    1 |
|    2 |
|    3 |
|    4 |
+——-+
5 rows in set (0.00 sec)
⼀⾏就是执⾏结果,实际的作⽤和使⽤while编写的存储过程⼀样,都是插⼊5⾏数据。
再来看⼀下第三个循环控制语句LOOP……END LOOP。编写⼀个存储过程程序如下:
mysql> create procedure pro12()
-> begin
-> declare i int default 0;
-> loop_label: loop
->    insert into t1(filed) values(i);
->    set i=i+1;
->    if i>=5 then
->        leave loop_label;
-
>    end if;
-> end loop;
-> end;//
Query OK, 0 rows affected (0.00 sec)
从上⾯这个例⼦可以看出,使⽤LOOP编写同样的循环控制语句要⽐使⽤while和repeat编写的要复杂⼀些:在循环内部加⼊了IF……END IF语句,在IF语句中⼜加⼊了LEAVE语句,LEAVE语句的意思是离开循环,LEAVE的格式是:LEAVE 循环标号。
编写完存储过程程序后,来执⾏并查看⼀下运⾏结果:
mysql> delete from t1//
Query OK, 5 rows affected (0.00 sec)
mysql> call pro12//
Query OK, 1 row affected (0.00 sec) #虽然说只有⼀⾏数据受影响,但是实际上是插⼊了5⾏数据。
mysql> select * from t1//
+——-+
| filed |
+——-+
|    0 |
|    1 |
|    2 |
|    3 |
|    4 |
+——-+
5 rows in set (0.00 sec)
执⾏结果和使⽤WHILE、LOOP编写的循环⼀样,都是往标中插⼊5⾏值。
Labels  标号和 END Labels 结束标号
html高级代码在使⽤loop的时候,使⽤到的labels标号,对于labels可以⽤到while,loop,rrepeat等循环控制语句中。⽽且有必要好好认识⼀下lables!!
mysql> create procedure pro13()
-> label_1:begin
-> label_2:while 0=1 do leave label_2;end while;
-> label_3:repeat leave label_3;until 0=0 end repeat;
-> label_4:loop leave label_4;end loop;
-> end;//
Query OK, 0 rows affected (0.00 sec)
上⾯这⾥例⼦显⽰了可以在BEGIN、WHILE、REPEAT或者LOOP语句前使⽤语句标号,语句标号只能在合法的语句前使⽤,所以LEAVE label_3意味着离开语句标号名为label_3的语句或符合语句。
其实,也可以使⽤END labels来表⽰标号结束符。
mysql> create procedure pro14()
-> label_1:begin
-> label_2:while 0=1 do leave label_2;end while label_2;
-> end label_1;//
Query OK, 0 rows affected (0.00 sec)
上⾯就是使⽤了标号结束符,其实这个结束标号并不是⼗分有⽤,⽽且他必须和开始定义的标号名字⼀样,否则就会报错。如果要养成⼀个良好的编程习惯⽅便他⼈阅读的话,可以使⽤这个标号结束符。
ITERATE 迭代
如果是在ITERATE语句,即迭代语句中的话,就必须使⽤LEAVE语句。ITERATE只能出现在LOOP,REPEAT和WHILE语句中,它的意思是“再次循环”,例如:
mysql> create procedure pro15()
-> begin
-> declare i int default 0;
-> loop_label:loop
->    if i=3 then
->        set i=i+1;
->        iterate loop_label;
->    end if;
->    insert into t1(filed) values(i);
->    set i=i+1;
->    if i>=5 then
->        leave loop_label;
->    end if;
->  end loop;
-> end;//
Query OK, 0 rows affected (0.00 sec)
iterate语句和leave语句⼀样,也是在循环内部使⽤,它有点类似于C/C++语⾔中的continue。
那么这个存储程序是怎么运⾏的的?⾸先i的值为0,条件判断语句if i=3 then判断为假,跳过if语段,向数据库中插⼊0,然后i+1,同样后⾯的if i>=5 then判断也为假,也跳过;继续循环,同样插⼊1和2;在i=3的时候条件判断语句if i=3 then判断为真,执⾏i=i+1,i值为4,然后执⾏迭代iterate loop_label;,即语句执⾏到iterate loop_label;后直接跳到if i=3 then判断语句,执⾏判断,这个时候由于i=4,if i=3 then判断为假,跳过IF语段,将4添加到表中,i变为5,条件判断if i>=5 then判断为真,执⾏leave loop_label;跳出loop循环,然后执⾏end;//,结束整个存储过程。
综上所述,数据库中将插⼊数值:0,1,2,4。执⾏存储过程,并查看结果:|
mysql> delete from t1//
Query OK, 5 rows affected (0.00 sec)
mysql> call pro15//
Query OK, 1 row affected (0.00 sec)
什么是字符串变量mysql> select * from t1//
+——-+
| filed |
+——-+
|    0 |
|    1 |
|    2 |
|    4 |
+——-+
4 rows in set (0.00 sec)
和我们上⾯分析的结果⼀样,只插⼊了数值0,1,2,4。
存储过程如同⼀门程序设计语⾔,同样包含了数据类型、流程控制、输⼊和输出和它⾃⼰的函数库。
--------------------基本语法--------------------
⼀.创建存储过程
create procedure sp_name()
begin
.........
end
⼆.调⽤存储过程
1.基本语法:call sp_name()
注意:存储过程名称后⾯必须加括号,哪怕该存储过程没有参数传递
三.删除存储过程
1.基本语法:
drop procedure sp_name//
2.注意事项
(1)不能在⼀个存储过程中删除另⼀个存储过程,只能调⽤另⼀个存储过程
四.其他常⽤命令
1.show procedure status
显⽰中所有存储的存储过程基本信息,包括所属数据库,存储过程名称,创建时间等
2.show create procedure sp_name
显⽰某⼀个存储过程的详细信息
--------------------数据类型及运算符--------------------
⼀、基本数据类型:
⼆、变量:
⾃定义变量:DECLARE  a INT ; SET a=100;    可⽤以下语句代替:DECLARE a INT DEFAULT 100;
变量分为⽤户变量和系统变量,系统变量⼜分为会话和全局级变量
⽤户变量:⽤户变量名⼀般以@开头,滥⽤⽤户变量会导致程序难以理解及管理
1、在mysql客户端使⽤⽤户变量
mysql> SELECT 'Hello World' into @x;
mysql> SELECT @x;
mysql> SET @y='Goodbye Cruel World';
mysql> select @y;
mysql> SET @z=1+2+3;
mysql> select @z;
2、在存储过程中使⽤⽤户变量
mysql> CREATE PROCEDURE GreetWorld( ) SELECT CONCAT(@greeting,' World');
mysql> SET @greeting='Hello';
mysql> CALL GreetWorld( );
3、在存储过程间传递全局范围的⽤户变量
mysql> CREATE PROCEDURE p1( )  SET @last_procedure='p1';
mysql> CREATE PROCEDURE p2( ) SELECT CONCAT('Last procedure was ',@last_procedure);
mysql> CALL p1( );
mysql> CALL p2( );
三、运算符:
1.算术运算符
+    加  SET var1=2+2;      4
-    减  SET var2=3-2;      1
*      乘  SET var3=3*2;      6
/    除  SET var4=10/3;      3.3333
DIV  整除 SET var5=10 DIV 3; 3
%    取模 SET var6=10%3 ;    1
2.⽐较运算符
>            ⼤于 1>2 False
<            ⼩于 2<1 False
<=          ⼩于等于 2<=2 True
>=          ⼤于等于 3>=2 True
BETWEEN      在两值之间 5 BETWEEN 1 AND 10 True
NOT BETWEEN 不在两值之间 5 NOT BETWEEN 1 AND 10 False
IN          在集合中 5 IN (1,2,3,4) False
NOT IN      不在集合中 5 NOT IN (1,2,3,4) True
=            等于 2=3 False
<>, !=      不等于 2<>3 False
<=>          严格⽐较两个NULL值是否相等 NULL<=>NULL True
LIKE          简单模式匹配 "Guy Harrison" LIKE "Guy%" True
REGEXP      正则式匹配 "Guy Harrison" REGEXP "[Gg]reg" False
IS NULL      为空 0 IS NULL False
IS NOT NULL 不为空 0 IS NOT NULL True
3.逻辑运算符
4.位运算符
|  或
&  与
<< 左移位
>> 右移位
~  ⾮(单⽬运算,按位取反)
注释:
mysql存储过程可使⽤两种风格的注释
双横杠:--
c风格:/* 注释内容 */ ⼀般⽤于多⾏注释
--------------------流程控制--------------------
⼀、顺序结构
⼆、分⽀结构
if
case
三、循环结构
for循环
while循环
loop循环
repeat until循环
注:
区块定义,常⽤
begin
......
end;
也可以给区块起别名,如:
lable:begin
...........
end lable;
可以⽤leave lable;跳出区块,执⾏区块以后的代码。
可以提前退出存储过程(函数直接return)。
begin和end如同C语⾔中的{ 和 }。
--------------------输⼊和输出--------------------
mysql存储过程的参数⽤在存储过程的定义,共有三种参数类型,IN,OUT,INOUT
Create procedure|function([[IN |OUT |INOUT ] 参数名数据类形...])
IN 输⼊参数
表⽰该参数的值必须在调⽤存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值OUT 输出参数
该值可在存储过程内部被改变,并可返回
INOUT 输⼊输出参数
调⽤时指定,并且可被改变和返回
IN参数例⼦:
CREATE PROCEDURE sp_demo_in_parameter(IN p_in INT)
BEGIN
SELECT p_in; --查询输⼊参数
SET p_in=2; --修改
select p_in;--查看修改后的值
END;
执⾏结果:
mysql> set @p_in=1
mysql> call sp_demo_in_parameter(@p_in)
mysql> select @p_in;
以上可以看出,p_in虽然在存储过程中被修改,但并不影响@p_id的值
OUT参数例⼦
创建:
mysql> CREATE PROCEDURE sp_demo_out_parameter(OUT p_out INT)
BEGIN
SELECT p_out;/*查看输出参数*/
SET p_out=2;/*修改参数值*/
SELECT p_out;/*看看有否变化*/
END;
执⾏结果:
mysql> SET @p_out=1
mysql> CALL sp_demo_out_parameter(@p_out)
mysql> SELECT @p_out;
INOUT参数例⼦:
mysql> CREATE PROCEDURE sp_demo_inout_parameter(INOUT p_inout INT)
BEGIN
SELECT p_inout;
SET p_inout=2;
SELECT p_inout;
END;
执⾏结果:
set @p_inout=1
call sp_demo_inout_parameter(@p_inout) //
select @p_inout;
附:函数库
mysql存储过程基本函数包括:字符串类型,数值类型,⽇期类型
⼀、字符串类
CHARSET(str) //返回字串字符集
CONCAT (string2 [,… ]) //连接字串
INSTR (string ,substring ) //返回substring⾸次在string中出现的位置,不存在返回0
LCASE (string2 ) //转换成⼩写
LEFT (string2 ,length ) //从string2中的左边起取length个字符
LENGTH (string ) //string长度
LOAD_FILE (file_name ) //从⽂件读取内容
LOCATE (substring , string [,start_position ] ) 同INSTR,但可指定开始位置
LPAD (string2 ,length ,pad ) //重复⽤pad加在string开头,直到字串长度为length
LTRIM (string2 ) //去除前端空格
REPEAT (string2 ,count ) //重复count次
REPLACE (str ,search_str ,replace_str ) //在str中⽤replace_str替换search_str
RPAD (string2 ,length ,pad) //在str后⽤pad补充,直到长度为length
RTRIM (string2 ) //去除后端空格
STRCMP (string1 ,string2 ) //逐字符⽐较两字串⼤⼩,
SUBSTRING (str , position [,length ]) //从str的position开始,取length个字符,
注:mysql中处理字符串时,默认第⼀个字符下标为1,即参数position必须⼤于等于1
mysql> select substring(’abcd’,0,2);
+———————–+
| substring(’abcd’,0,2) |
+———————–+
|                      |
+———————–+
1 row in set (0.00 sec)
mysql> select substring(’abcd’,1,2);
+———————–+
后台管理界面设计| substring(’abcd’,1,2) |
+———————–+
| ab                    |
+———————–+
1 row in set (0.0
2 sec)
TRIM([[BOTH|LEADING|TRAILING] [padding] FROM]string2) //去除指定位置的指定字符UCASE (string2 ) //转换成⼤写
RIGHT(string2,length) //取string2最后length个字符
SPACE(count) //⽣成count个空格
⼆、数值类型
ABS (number2 ) //绝对值
BIN (decimal_number ) //⼗进制转⼆进制
CEILING (number2 ) //向上取整
CONV(number2,from_base,to_base) //进制转换
FLOOR (number2 ) //向下取整
FORMAT (number,decimal_places ) //保留⼩数位数
HEX (DecimalNumber ) //转⼗六进制
注:HEX()中可传⼊字符串,则返回其ASC-11码,如HEX(’DEF’)返回4142143
也可以传⼊⼗进制整数,返回其⼗六进制编码,如HEX(25)返回19
LEAST (number , number2 [,..]) //求最⼩值
MOD (numerator ,denominator ) //求余
POWER (number ,power ) //求指数
RAND([seed]) //随机数
ROUND (number [,decimals ]) //四舍五⼊,decimals为⼩数位数]
注:返回类型并⾮均为整数,如:
mysql> select round(1.23);
+————-+
| round(1.23) |
+————-+
|          1 |
+————-+
1 row in set (0.00 sec)
mysql> select round(1.56);
+————-+
| round(1.56) |
+————-+
|          2 |
+————-+
1 row in set (0.00 sec)
(2)可以设定⼩数位数,返回浮点型数据
mysql> select round(1.567,2);
+—————-+
| round(1.567,2) |
+—————-+
|          1.57 |
+—————-+
1 row in set (0.00 sec)
SIGN (number2 ) //返回符号,正负或0
SQRT(number2) //开平⽅
三、⽇期类型如何对java源码进行加密
ADDTIME (date2 ,time_interval ) //将time_interval加到date2
CONVERT_TZ (datetime2 ,fromTZ ,toTZ ) //转换时区
CURRENT_DATE ( ) //当前⽇期
CURRENT_TIME ( ) //当前时间
CURRENT_TIMESTAMP ( ) //当前时间戳
DATE (datetime ) //返回datetime的⽇期部分
DATE_ADD (date2 , INTERVAL d_value d_type ) //在date2中加上⽇期或时间
DATE_FORMAT (datetime ,FormatCodes ) //使⽤formatcodes格式显⽰datetime
DATE_SUB (date2 , INTERVAL d_value d_type ) //在date2上减去⼀个时间
DATEDIFF (date1 ,date2 ) //两个⽇期差
DAY (date ) //返回⽇期的天
DAYNAME (date ) //英⽂星期
DAYOFWEEK (date ) //星期(1-7) ,1为星期天
DAYOFYEAR (date ) //⼀年中的第⼏天
EXTRACT (interval_name FROM date ) //从date中提取⽇期的指定部分
MAKEDATE (year ,day ) //给出年及年中的第⼏天,⽣成⽇期串
MAKETIME (hour ,minute ,second ) //⽣成时间串
MONTHNAME (date ) //英⽂⽉份名
NOW ( ) //当前时间
SEC_TO_TIME (seconds ) //秒数转成时间
STR_TO_DATE (string ,format ) //字串转成时间,以format格式显⽰
TIMEDIFF (datetime1 ,datetime2 ) //两个时间差
TIME_TO_SEC (time ) //时间转秒数]
WEEK (date_time [,start_of_week ]) //第⼏周
YEAR (datetime ) //年份
DAYOFMONTH(datetime) //⽉的第⼏天
HOUR(datetime) //⼩时
LAST_DAY(date) //date的⽉的最后⽇期
MICROSECOND(datetime) //微秒
MONTH(datetime) //⽉
MINUTE(datetime) //分
注:可⽤在INTERVAL中的类型:DAY ,DAY_HOUR ,DAY_MINUTE ,DAY_SECOND ,HOUR ,HOUR_MINUTE ,HOUR_SECOND ,MINUTE ,MINUTE_SECOND,MONTH ,SECOND ,YEAR DECLARE variable_name [,] datatype [DEFAULT value];
其中,datatype为mysql的数据类型,如:INT, FLOAT, DATE, VARCHAR(length)
例:
DECLARE l_int INT unsigned default 4000000;
DECLARE l_numeric NUMERIC(8,2) DEFAULT 9.95;
DECLARE l_date DATE DEFAULT '1999-12-31';
DECLARE l_datetime DATETIME DEFAULT '1999-12-31 23:59:59';
DECLARE l_varchar VARCHAR(255) DEFAULT 'This will not be padded';
ORACLE与MYSQL的存储过程/函数的使⽤区别
类别ORACLE MYSQL注释
1创建存储过程语句
不同create or replace procedure
P_ADD_FAC(
id_fac_cd  IN
ES_FAC_UNIT.FAC_CD%TYPE) is
DROP PROCEDURE IF EXISTS
`SD_USER_P_ADD_USR`;
create procedure P_ADD_FAC(
id_fac_cd  varchar(100))
1.在创建存储过程时如果存在同名的存储过程,会删除⽼
的存储过程.
oracle使⽤create or replace.
mysql使⽤先删除⽼的存储过程,然后再创建新的存储过
程.
2. oracle 存储过程可以定义在package中,也可以定义在
Procedures中. 如果定义在包中,⼀个包中可以包含多个
存储过程和⽅法.如果定义在Procedures中,存储过程中不
可以定义多个存储过程.
Mysql  存储过程中不可以定义多个存储过程.
3. oracle中字符串类型可以使⽤varchar2.
Mysql 需要使⽤varchar
4. Oracle中参数varchar长度不是必须的,
Mysql中参数varchar长度是必须的, ⽐如varchar(100)
2创建函数语句不同CREATE OR REPLACEFUNCTION
F_ROLE_FACS_GRP(
ii_role_int_key IN
SD_ROLE.ROLE_INT_KEY%TYPE
) RETURN VARCHAR2
DROP FUNCTION IF EXISTS
`SD_ROLE_F_ROLE_FACS_GRP`;
CREATE  FUNCTION
`SD_ROLE_F_ROLE_FACS_GRP`(
ii_role_int_key INTEGER(10)
) RETURNS varchar(1000)
1.在创建函数时如果存在同名的函数,会删除⽼的函数.
oracle使⽤create or replace.
mysql使⽤先删除⽼的函数,然后再创建新的函数.
2. oracle 函数可以定义在package中,也可以定义在
Functions中. 如果定义在包中,⼀个包中可以包含多个存
储过程和函数.如果定义在Functions中,每个函数只能定义
⼀个函数.
Mysql  Functions不可以定义多个函数.
3.  oracle返回值⽤return.
Mysql返回值⽤returns.
3传⼊参数写法不同procedure P_ADD_FAC(
id_fac_cd  IN
ES_FAC_UNIT.FAC_CD%TYPE)
create procedure P_ADD_FAC(
(in) id_fac_cd  varchar(100))
1. oracle存储过程参数可以定义为表的字段类型.
Mysql存储过程不⽀持这种定义⽅法.需要定义变量的实
际类型和长度.
2. oracle 参数类型in/out/inout写在参数名后⾯.
Mysql  参数类型in/out/inout写在参数名前⾯.
3. oracle 参数类型in/out/inout 都必须写.
Mysql  参数类型如果是in,则可以省略. 如果是out或
inout则不能省略.
注意: mysql中指定参数为IN, OUT, 或INOUT 只对
PROCEDURE是合法的。(FUNCTION参数总是被认为
是IN参数) RETURNS字句只能对FUNCTION做指定,
对函数⽽⾔这是强制的。它⽤来指定函数的返回类型,⽽
且函数体必须包含⼀个RETURN value语句。
function func_name(
gw_id  in(out)  varchar2 )
create function func_name(
gw_id varchar(100))
4包的声明⽅式create or replace
package/package body package
name
拆分成多个存储过程或函数
oracle可以创建包,包中可以包含多个存储过程和⽅法.
mysql没有没有包这个概念,可以分别创建存储过程和⽅
法. 每个存储过程或⽅法都需要放在⼀个⽂件中.
例1: ⽅法命名
oracle 中SD_FACILITY_PKG.F_SEARCH_FAC
to mysql SD_FACILITY_F_SEARCH_FAC
例2: 过程命名
oracle 中SD_FACILITY_PKG.P_ADD_FAC
to mysql SD_FACILITY_P_ADD_FAC
5存储过程返回语句return;LEAVE proc; (proc 代表最外层
oracle存储过程和⽅法都可以使⽤return退出当前过程和
⽅法.
Mysql存储过程中只能使⽤leave退出当前存储过程.不可
异常处理
MySQL 的GET DIAGNOSTICS 语句
这是⼀个把我困扰已久的问题,今天偶然间解决了。
以前⽤Oracle 时经常会⽤到的三个东西:sql%rowcount 、SQLCODE 、SQLERRM
sql%rowcount ⽤于记录最近⼀条DML 语句修改的记录条数,就如你在sqlplus 下执⾏delete from 之后提⽰已删除xx ⾏⼀样。SQLCODE 和SQLERRM 是Oracle 的异常处理函数,常被⽤于得到完整错误提⽰信息,⽅便错误时处理。
那么问题来了,MySQL 有没有相似的功能呢?以前查了很久也没有到好的解决办法,然⽽在5.6.4以后,MySQL 提供了GET DIAGNOSTICS 语法,那么我的问题也随之迎刃⽽解。简单讲GET DIAGNOSTICS 能提供以下两种信息:语句信息,例如错误信息号或者语句影响的⾏数。错误信息,例如错误号和错误消息。
如果⼀条语句产⽣了三种错误,诊断区域包含的语句和错误信息类似这样:
Statement information: row count ... other statement information items ... Condition area list: Condition area 1: error code for condition 1 error message for condition 1 ... other condition information items ... Condition area 2: error code for condition 2: error m 使⽤GET DIAGNOSTICS 需要注意的是,它或者包含语句信息,或者包含错误信息,但⼀个GET DIAGNOSTICS 不会同时包含语句信息和错误信息,所以需要⽤两个GET DIAGNOSTICS 来获得语句信息和错误信息。获得语句信息:
GET DIAGNOSTICS @p1 = NUMBER, @p2 = ROW_COUNT;
获得错误信息:
GET DIAGNOSTICS CONDITION 1 @p3 = RETURNED_SQLSTATE, @p4 = MESSAGE_TEXT;语句信息条⽬名称有:NUMBER
| ROW_COUNT
错误信息条⽬名称有:CLASS_ORIGIN
| SUBCLASS_ORIGIN | RETURNED_SQLSTATE | MESSAGE_TEXT | MYSQL_ERRNO
| CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | CATALOG_NAME | SCHEMA_NAME | TABLE_NAME | COLUMN_NAME | CURSOR_NAME
为了确保获得正确的主错误信息,必须使⽤类似如下的语句:GET DIAGNOSTICS @cno = NUMBER;
GET DIAGNOSTICS CONDITION @cno @errno = MYSQL_ERRNO;最后来看⼀个使⽤GET DIAGNOSTICS 完整例⼦(摘⾃官⽅⽂档)
结果:insert failed, error = 42S02, message = Table 'ud_omcs.t1' doesn't exist
Mysql ⽅法可以使⽤return 退出当前⽅法.
6
存储过程异常处理不⼀样
EXCEPTION
WHEN OTHERS THEN    ROLLBACK ;
ov_rtn_msg := c_sp_name||'('||li_debug_pos ||'):'||
TO_CHAR(SQLCODE)||':'||SUBSTR(SQLERRM,1,100);
DECLARE EXIT HANDLER FOR SQLEXCEPTION  BEGIN
ROLLBACK ;
set ov_rtn_msg =concat(c_sp_name,'(',li_debug_pos ,'):',
TO_CHAR(SQLCODE),':',SUBSTR(SQLERRM,1,100)); END;
oracle : 内部异常不需要定义,在存储过程或函数末尾写上EXCEPTION 后,后⾯的部分即为异常处理的部分.  oracle 可以定义⾃定义异常,⾃定义异常需要使⽤raise 关键字抛出异常后,才可以在EXCEPTION 中捕获.
mysql: mysql 内部异常也需要先定义,在定义的同时也需要实现异常的功能.
⽬前mysql 不⽀持⾃定义异常. 7
过程和函数的声明变量的位置不同
声明变量在begin…end 体之前声明变量在d 体
内,begin 之后其他任何内容之前
8
NO_DATA_FOUND 异常处理 EXCEPTION
WHEN NO_DATA_FOUND THEN
oi_rtn_cd := 1;            ov_rtn_msg :=
SD_COMMON.P_GET_MSG('DP-CBM-01100a-016',
li_sub_rtn_cd,
lv_sub_rtn_msg
);使⽤FOUND_ROWS()代替NO_DATA_FOUND. 详见注释.
oracle 中:
NO_DATA_FOUND 是游标的⼀个属性.
当select 没有查到数据就会出现 no data found 的异常,程序不会向下执⾏.
Mysql:
没有NO_DATA_FOUND 这个属性.但可是使⽤
FOUND_ROWS()⽅法得到select 语句查询出来的数据.如果FOUND_ROWS()得到的值为0,就进⼊异常处理逻辑. 9在存储过程中调⽤存储过程⽅式的不同
Procedure_Name(参数);Call Procedure_Name(参数);MYSQL 存储过程调⽤存储过程,需要使⽤Call pro_name(参数).
Oracle 调⽤存储过程直接写存储过程名就可以了. 10mysql查看所有存储过程
抛异常的⽅式不同
RAISE Exception_Name;
见备注
详见<<2009002-OTMPPS-Difficult Questions-0001.doc>>中2.5 Mysql 异常处理部分
BEGIN
-- Declare variables to hold diagnostics area information DECLARE code CHAR(5) DEFAULT '00000'; DECLARE msg TEXT; DECLARE rows INT; DECLARE result TEXT;
-- Declare exception handler for failed insert
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN
GET DIAGNOSTICS CONDITION 1 code = RETURNED_SQLSTATE, msg = MESSAGE_TEXT; END;
-- Perform the insert
INSERT INTO t1 (int_col) VALUES(value);
-- Check whether the insert was successful IF code = '00000' THEN
GET DIAGNOSTICS rows = ROW_COUNT;
SET result = CONCAT('insert succeeded, row count = ',rows); ELSE
SET result = CONCAT('insert failed, error = ',code,', message = ',msg); END IF;
-- Say what happened SELECT result; END

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。