存储过程(详细-附样例)

发布于:2024-12-21 ⋅ 阅读:(15) ⋅ 点赞:(0)

所有样例都是在mysql5.7版本下执行的,如果用其他数据库,请根据对应的数据库存储过程定义更改语句。

主体目录

一、存储过程相关命令

二、存储过程

2、参数

3、变量

4、if 流程控制

5、case 条件控制

6、while 循环语句

7、repeat 循环语句

8、loop 循环语句

9、游标

10、条件处理(捕捉异常并处理)


请以左边系统目录为准

一、存储过程相关命令

序号 命令 注释
1 SHOW PROCEDURE STATUS; 查看所有存储过程信息
2 SHOW CREATE PROCEDURE 存储过程名; 查看存储过程源码
3 DROP PROCEDURE 存储过程名; 删除存储过程
4 CALL  存储过程名(‘输入参数’,@输出参数名); 调用存储过程,如无参数,括号里留空

系统表information_schema.ROUTINES里是存储过程的详细信息:information_schema.ROUTINES 是MySQL中的一个系统表,存储了所有存储过程、函数、触发器的详细信息,包括名称、返回值类型、参数、创建时间、修改时间等。

二、存储过程

1、基本的存储过程

1.基本样例

#改变语句结束符为//。
DELIMITER //
#创建存储过程名称([ 参数列表 ])。参数列表可以为空
create procedure name_count()

#存储过程执行代码的开头
begin

    #查询某个数据库里有多少张表
    select table_schema,count(*) from information_schema.tables where TABLE_SCHEMA = 'ling';

#存储过程执行代码的结尾
end //
#改变语句结束符为;。是将语句结束符改回;。
DELIMITER ;
#调用存储过程
CALL  name_count();

2. 基本样例语句命令详细说明

 1)delimiter

DELIMITER的主要作用是改变语句结束符。MySQL默认是使用分号 ; 作为语句结束符。但是在编写存储过程、函数等复杂SQL时,需要在代码块中使用分号来结束单个SQL语句,包含多个SQL语句。这时候就需要DELIMITER命令来临时改变默认的语句结束符。告诉mysql,遇到指定符号再执行

注: 不同数据库的存储定义可能不一样,delimiter有时可省略。

样例

#改变语句结束符为//。
DELIMITER //

#中间放存储过程语句

#改变语句结束符为;。是将语句结束符改回;。一般可以省略
DELIMITER ;
2)create procedure 存储过程名称( [参数列表] )

create procedure:创建存储过程。

注:参数列表里的注释放在下面的带参数样例语句命令详细说明

样例

#格式
CREATE PROCEDURE `库名`.`存储过程名称`(IN/OUT/INOUT 参数名 参数类型)

#样例
CREATE PROCEDURE name_s()

CREATE PROCEDURE `ling`.`name_s`()

CREATE PROCEDURE `name_ku`.`name_s`(IN sx varchar(255),OUT sx_count INT)
 3)begin、end

存储过程的架构,BEGIN是开始,END是结束。

存储过程语句必须在BEGIN和END之间。

2、参数

 1. 语法格式:

#格式
CREATE PROCEDURE `库名`.`存储过程名称`(IN/OUT/INOUT 参数名 参数类型)

#样例
CREATE PROCEDURE name_s()

CREATE PROCEDURE `ling`.`name_s`()

CREATE PROCEDURE `name_ku`.`name_s`(IN sx varchar(255),OUT sx_count INT)

参数列表

存储过程中的参数列表分别有 in,out,inout三种类型;

1、in:输入参数(默认为in参数),该参数的值必须由存储过程制定。
2、ou:输出参数,该参数的值经存储过程计算后,将out参数的计算结果返回给调用的存储过程。
3、inout:即是输入参数,又是输出参数,该参数的值即可有储过程制定,又可以将inout参数的计算结果返回给调用的存储过程。

注:into 是赋值函数,将某个值,赋值给另一个。

 2.参数样例

#改变语句结束符为//。
DELIMITER //

#创建存储过程名称([ 参数列表 ])。参数列表可以为空
#定义了输入参数naname,输出参数naname_count
create procedure name_count1(IN naname VARCHAR(100),OUT naname_count VARCHAR(100))

#存储过程执行代码的开头
begin

	#查询某个数据库里有多少张表
	select CONCAT_WS('',table_schema,'库表总数:',count(*))  into naname_count  from information_schema.tables where TABLE_SCHEMA = naname;
    #调用后直接查询出参数结果
    #select naname_count;
#存储过程执行代码的结尾
end //
#改变语句结束符为;。是将语句结束符改回;。
DELIMITER ;
#调用存储过程,第一个是输入的参数,第二个是输出
CALL name_count1('ling',@naname_count);

select @naname_count;

注: 想要直接call调用后直接出结果,而不是调用后再select查询,则要将select语句放到存储过程中,在存储过程执行代码的结尾end上面一行添加select语句即可。

语句样例中有,把注释去掉即可。

3、变量

1. 语法格式:

#声明变量name_s ,数据类型是VARCHAR,默认值是空
DECLARE name_s VARCHAR(10) DEFAULT '';

#声明变量sceor ,数据类型是int ,默认值是5000
DECLARE sceor int DEFAULT 5000;

#把1赋值给name_s变量
set name_s = "1" ;
set name_s := "1" ;

在存储过程中使用的是局部变量,只在存储过程中生效

1、declare:声明变量

2、default:变量默认赋值

注:set 是赋值操作,跟into的作用一样,将某个值,赋值给另一个。

2.变量样例

#改变语句结束符为//。
DELIMITER //

#创建存储过程名称([ 参数列表 ])。参数列表可以为空。不需要参数的可把参数去了
create procedure name_count2(IN naname VARCHAR(100),OUT naname_count VARCHAR(100))

#存储过程执行代码的开头
begin

	#声明,用来声明变量的,DEFAULT后面也可留空''。
	DECLARE name_s VARCHAR(10) DEFAULT '表总数';

	#set可用来改变值, 变量=值
	set name_s ="库表总数:";

	#查询某个数据库里有多少张表
		select CONCAT_WS('',table_schema,name_s,count(*))  into naname_count  from information_schema.tables where TABLE_SCHEMA = naname;

#存储过程执行代码的结尾
end //
#改变语句结束符为;。是将语句结束符改回;。
DELIMITER ;
#调用存储过程,第一个是输入的参数,第二个是输出
CALL name_count2('ling',@naname_count);

select @naname_count;

4、if 流程控制

1.语法格式:

if 条件1 then
......(此处是满足条件后进行的操作)
elseif 条件2 then
......(此处是满足条件后进行的操作)
elseif 条件3 then
......(此处是满足条件后进行的操作)
else
......(此处是都不满足前面的条件后进行的操作)
end if;

2.if 语句样例

 1)样例1

判断输入的成绩是否合格

score >= 90分,等级为优秀。

score >= 75分 且 score < 90分,为优良。

score >= 60分 且 score < 75分,为及格。

score < 60分,为不及格。

#改变语句结束符为//。
DELIMITER //
#创建存储过程名称([ 参数列表 ])。参数列表可以为空。不需要参数的可把参数去了
create procedure name_if_score(IN score int)

#存储过程执行代码的开头
begin 
	#定义变量
    declare rating varchar(100);
    #if判断
    if score >= 90 and score <= 100 then
        set rating := '优秀';
    elseif score >= 75 and score < 90 then
        set rating := '优良';
    elseif score >= 60 and score < 75 then
        set rating := '及格';
    elseif score >= 0 and score < 60 then
        set rating := '不及格';
    else
        set rating := '参数错误,请重新输入成绩';
    end if;
    select rating;
		
#存储过程执行代码的结尾
end //
#改变语句结束符为;。是将语句结束符改回;。
DELIMITER ;
call name_if_score('76');

 2)样例2

判断输入的收入等级

超过10000的属于“高收入”。

6000到10000的属于“中收入”。

少于6000的属于“低收入”。

#改变语句结束符为//。
DELIMITER //
#创建存储过程名称([ 参数列表 ])。参数列表可以为空。不需要参数的可把参数去了
create procedure name_if_salary(IN salary int)

#存储过程执行代码的开头
begin 
	#if判断
	if salary >= 10000 and salary <= 9999999 then
		select '高收入';
	elseif salary >= 6000 and salary <10000 then
		select '中收入';
	elseif salary < 6000  and salary >=0  then
		select '低收入';
    else
        select '参数错误,请重新输入收入';
    end if;
		
#存储过程执行代码的结尾
end //
#改变语句结束符为;。是将语句结束符改回;。
DELIMITER ;
call name_if_salary('6300');

5、case 条件控制

1.语法格式:

1)格式1
case
	when 条件1 then
	......(此处是满足条件后进行的操作)
	when 条件2 then
	......(此处是满足条件后进行的操作)
	when 条件3 then
	......(此处是满足条件后进行的操作)
	else
	......(此处是都不满足前面的条件后进行的操作)
end case;
2)格式2
case 值
	when 条件1 then
	......(此处是满足条件后进行的操作)
	when 条件2 then
	......(此处是满足条件后进行的操作)
	when 条件3 then
	......(此处是满足条件后进行的操作)
	else
	......(此处是都不满足前面的条件后进行的操作)
end case;

2.case 语句样例

 1)样例1

判断输入的月份是那一季节

1-3月份,为春季

4-6月份,为夏季

7-9月份,为秋季

10-12月份,为冬季

#改变语句结束符为//。
DELIMITER //
#创建存储过程名称([ 参数列表 ])。参数列表可以为空。不需要参数的可把参数去了
create procedure name_case_month(IN month int)

#存储过程执行代码的开头
begin 
	#定义变量
    declare season varchar(15);
    #case判断
    case
        when month >= 1 and month <= 3 then
            set season = '春季';
        when month >= 4 and month <= 6 then
            set season = '夏季';
        when month >= 7 and month <= 9 then
            set season = '秋季';
        when month >= 10 and month <= 12 then
            set season = '冬季';
        else
            set season = '参数错误,请重新输入月份';
        end case ;
    select concat('输入的月份是: ',month, ', 所属的季节是: ',season);
		
#存储过程执行代码的结尾
end //
#改变语句结束符为;。是将语句结束符改回;。
DELIMITER ;
call name_case_month(11);

 2)样例2

判断输入的数字是星期几

1到7分别对应星期一到星期日

#改变语句结束符为//。
DELIMITER //
#创建存储过程名称([ 参数列表 ])。参数列表可以为空。不需要参数的可把参数去了
create procedure name_case_week(IN week int)

#存储过程执行代码的开头
begin 

    #case判断
    case week
        when   1  then
            select '星期一';
				when   2  then
            select '星期二';
				when   3  then
            select '星期三';
				when   4  then
            select '星期四';
				when   5  then
            select '星期五';
				when   6  then
            select '星期六';
				when   7  then
            select '星期日';
        else
            select '参数错误,请重新输入';
        end case ;
		
#存储过程执行代码的结尾
end //
#改变语句结束符为;。是将语句结束符改回;。
DELIMITER ;
call name_case_week(5);

6、while 循环语句

1.语法格式:

#判定是否符合条件,符合则执行循环,执行到不符合条件后停止循环;否则,不执行逻辑
while 条件 do
	循环内容;
end while;

2.while 语句样例

 1)样例1

执行传入的数字(bigit)对应的循环次数,每循环一次,数字加1

循环条件:每循环一次, 传入的数字进行减1 , 等传入的数字(bigit)减到0, 就退出循环。

循环结果:定义一个变量,变量是0,每循环一次加1,直到循环结束,输出最后的变量值。

#改变语句结束符为//。
DELIMITER //
#创建存储过程名称([ 参数列表 ])。参数列表可以为空。不需要参数的可把参数去了
create procedure name_while_bigit(IN bigit int)

#存储过程执行代码的开头
begin 
	#定义变量
	declare sum_n  int default 0;
	#while循环,符合条件就进行循环,执行到不符合条件后停止循环
	while bigit > 0 do 
		#循环内容
		set sum_n = sum_n + 1;
		#每次减1后重新赋值给bigit
		set bigit = bigit - 1;
  end while;
	
  select sum_n;

#存储过程执行代码的结尾
end //
#改变语句结束符为;。是将语句结束符改回;。
DELIMITER ;
call name_while_bigit(5);

2)样例2

传入一个数字(bigit),计算1~n中所有奇数的和。

循环条件:每循环一次, 传入的数字进行减1 , 等传入的数字(bigit)减到0, 就退出循环。

循环结果:定义一个变量,变量是0,每循环一次if判断是否为奇数,是的加该数,直到循环结束,输出最后的变量值。

#改变语句结束符为//。
DELIMITER //
#创建存储过程名称([ 参数列表 ])。参数列表可以为空。不需要参数的可把参数去了
create procedure name_while_bigit1(IN bigit int)

#存储过程执行代码的开头
begin 
	#定义变量
	declare sum_n  int default 0;
	#while循环,符合条件就进行循环,执行到不符合条件后停止循环
	while bigit > 0 do 
		#循环内容,判断当前数是否是奇数
		if mod(bigit,2)  = 1  then 
              #是奇数相加
		      set sum_n = sum_n + bigit;
		end if;
		#每次减1后重新赋值给bigit
		set bigit = bigit - 1;
  end while;
	
  select sum_n;

#存储过程执行代码的结尾
end //
#改变语句结束符为;。是将语句结束符改回;。
DELIMITER ;
call name_while_bigit1(3);

7、repeat 循环语句

1.语法格式:

#先执行一次循环体,然后判断 until 条件是否满足,如果满足,就退出循环。如果不满足,就继续循环,直到条件是否满足退出循环
repeat
	循环体;
	until 条件
end repeat;

2.repeat 语句样例

 1)样例1

 执行传入的数字(bigit)对应的循环次数,每循环一次,数字加1

循环条件:每循环一次, 传入的数字进行减1 , 等传入的数字(bigit)减到0, 就退出循环。

循环结果:定义一个变量,变量是0,每循环一次加1,直到循环结束,输出最后的变量值。

#改变语句结束符为//。
DELIMITER //
#创建存储过程名称([ 参数列表 ])。参数列表可以为空。不需要参数的可把参数去了
create procedure name_repeat_bigit(IN bigit int)

#存储过程执行代码的开头
begin 
	#定义变量
	declare sum_n  int default 0;
	#repeat循环,先执行一次循环体,然后判断 until 条件是否满足,如果满足,就退出循环。如果不满足,就继续循环,直到条件是否满足退出循环
	repeat  
		#循环内容
		set sum_n = sum_n + 1;
		#每次减1后重新赋值给bigit
		set bigit = bigit - 1;
		#判断循环条件
		until bigit <= 0
  end repeat;
	
  select sum_n;

#存储过程执行代码的结尾
end //
#改变语句结束符为;。是将语句结束符改回;。
DELIMITER ;
call name_repeat_bigit(5);

2)样例2

传入一个数字(bigit),计算1~n中所有奇数的和。

循环条件:每循环一次, 传入的数字进行减1 , 等传入的数字(bigit)减到0, 就退出循环。

循环结果:定义一个变量,变量是0,每循环一次if判断是否为奇数,是的加该数,直到循环结束,输出最后的变量值。

#改变语句结束符为//。
DELIMITER //
#创建存储过程名称([ 参数列表 ])。参数列表可以为空。不需要参数的可把参数去了
create procedure name_repeat_bigit1(IN bigit int)

#存储过程执行代码的开头
begin 
	#定义变量
	declare sum_n  int default 0;
	#repeat循环,先执行一次循环体,然后判断 until 条件是否满足,如果满足,就退出循环。如果不满足,就继续循环,直到条件是否满足退出循环
	repeat  
		#循环内容,判断当前数是否是奇数
		if mod(bigit,2)  = 1  then 
              #是奇数相加
		      set sum_n = sum_n + bigit;
		end if;
		#每次减1后重新赋值给bigit
		set bigit = bigit - 1;
		#判断循环条件
		until bigit <= 0
  end repeat;
	
  select sum_n;

#存储过程执行代码的结尾
end //
#改变语句结束符为;。是将语句结束符改回;。
DELIMITER ;
call name_repeat_bigit1(5);

8、loop 循环语句

1.语法格式:

#LOOP简单的循环,如果不在SQL中添加退出循环的条件,则会进入的死循环

LOOP循环名称:LOOP
    SQL...
END LOOP LOOP循环名称;

#在SQL使用的函数,用来退出和跳过loop循环。
leave:配合SQL循环使用,退出循环。
iterate:必须用在循环中,用来跳过此次循环后面的SQL,直接进入下一次循环。

2.loop 语句样例

 1)样例1

执行传入的数字(bigit)对应的循环次数,每循环一次,数字加1,传入数字(bigit)是偶数时,这次循环跳过。

循环条件:每循环一次, 传入的数字进行减1 , 等传入的数字(bigit)减到0, 就退出循环。

循环结果:定义一个变量,变量是0,每循环一次加1,传入数字(bigit)是偶数时,这次循环跳过。直到循环结束,输出最后的变量值。

 注:判断循环退出(ileave)条件,要在跳过循环(iterate)条件之前,并且在跳过循环(iterate)条件之前要给判断条件重新赋值。

#改变语句结束符为//。
DELIMITER //
#创建存储过程名称([ 参数列表 ])。参数列表可以为空。不需要参数的可把参数去了
create procedure name_loop_bigit(IN bigit int)

#存储过程执行代码的开头
begin 
	#定义变量
	declare sum_n  int default 0;
	#loop循环
	name_bigit:loop  
		#循环内容
		#判断循环退出条件
		if bigit <= 0 then
				#符合条件退出循环
				leave name_bigit; 
				
		#判断循环跳过条件
		elseif  bigit%2 = 0 THEN
				#跳过此次循环前先减1后重新赋值给bigit
				set bigit = bigit - 1;
				#符合条件跳过此次循环,进入下一次循环。
				iterate name_bigit;

		end if;

				set sum_n = sum_n + 1;
		#未跳过此次循环减1后重新赋值给bigit
				set bigit = bigit - 1;
  end loop name_bigit;
	
  select sum_n;

#存储过程执行代码的结尾
end //
#改变语句结束符为;。是将语句结束符改回;。
DELIMITER ;
call name_loop_bigit(5);

2)样例2

传入一个数字(bigit),计算1~n中所有奇数的和。不做跳过循环。

循环条件:每循环一次, 传入的数字进行减1 , 等传入的数字(bigit)减到0, 就退出循环。

循环结果:定义一个变量,变量是0,每循环一次if判断是否为奇数,是的加上该数,直到循环结束,输出最后的变量值。

#改变语句结束符为//。
DELIMITER //
#创建存储过程名称([ 参数列表 ])。参数列表可以为空。不需要参数的可把参数去了
create procedure name_loop_bigit1(IN bigit int)

#存储过程执行代码的开头
begin 
	#定义变量
	declare sum_n  int default 0;
	#loop循环
	name_bigit:loop  
		#循环内容
		#判断循环退出条件
		if bigit <= 0 then
				#符合条件退出循环
				leave name_bigit; 
		end if;

		#循环内容,判断当前数是否是奇数
		if mod(bigit,2)  = 1  then 
              #是奇数相加
		      set sum_n = sum_n + bigit;
		end if;
		
		#此次循环减1后重新赋值给bigit
				set bigit = bigit - 1;
  end loop name_bigit;
	
  select sum_n;

#存储过程执行代码的结尾
end //
#改变语句结束符为;。是将语句结束符改回;。
DELIMITER ;
call name_loop_bigit1(5);

9、游标

1.语法格式:

#声明游标
declare 游标名称 cursor for 查询语句;

#打开游标
open 游标名称;

#游标获取数据
fetch 游标名称 into 变量,变量,变量......

#关闭游标
close 游标名称;

2.游标 语句样例

 1)样例1

根据传入的数据库名,查询该数据库所有表的信息,并插入对应的结果存放表中。

定义变量:先定义需要字段的变量,用于后面游标获取数据后进行赋值。

声明游标:游标用来查询传入的数据库名的数据库所有表的信息。

建表清表:建一个结果存放表。并且清空下结果存放表,用于每次执行都是新的数据。

打开游标:使用游标前,要先打开游标。

循环处理:使用游标获取数据,并进行处理。

关闭游标:循环处理结束后,进行关闭游标

注:局部变量的声明需要在游标声明之前完成 

#改变语句结束符为//。
DELIMITER //
#创建存储过程名称([ 参数列表 ])。参数列表可以为空。不需要参数的可把参数去了
create procedure name_sql_date(IN nname varchar(25))

#存储过程执行代码的开头
begin 
	#定义变量
	DECLARE table_schema_1 varchar(255);
	DECLARE table_name_1 varchar(255);
	DECLARE table_comment_1 varchar(255);
	DECLARE table_rows_1 varchar(255);
	DECLARE data_size_1 varchar(255);
	DECLARE create_time_1 varchar(255);
	DECLARE update_time_1 varchar(255);
	
	#声明游标
	declare sql_schema_table cursor for select table_schema,table_name,table_comment,table_rows,( data_length / 1024 ) as data_size,create_time,update_time from information_schema.`tables` where  table_schema = nname;
	
	#创建结果存放表,字段顺序与上面查询语句的字段顺序一样
	    create table if not exists `schema_table` (
        `table_schema` VARCHAR ( 255 ) DEFAULT NULL COMMENT '数据库名称',
        `table_name` VARCHAR ( 257 ) DEFAULT NULL COMMENT '表英文名称',
        `table_comment` VARCHAR ( 258 ) DEFAULT NULL COMMENT '表中文名称',
        `table_rows` VARCHAR ( 259 ) DEFAULT NULL COMMENT '数据行数',
        `data_size` VARCHAR ( 260 ) DEFAULT NULL COMMENT '表大小',
        `create_time` VARCHAR ( 261 ) DEFAULT NULL COMMENT '创建时间',
        `update_time` VARCHAR ( 262 ) DEFAULT NULL COMMENT '更新时间'
    ) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT = '数据库-数据表相关信息';
	
	#清空结果存放表
	truncate table schema_table;
	
	#打开游标
	open sql_schema_table;
	
	#循环,true表示循环所有
  while true do
		#游标获取数据,并进行赋值。
        fetch sql_schema_table into table_schema_1,table_name_1,table_comment_1,table_rows_1,data_size_1,create_time_1,update_time_1;
		#将得到的数据进行插入结果存放表
        insert into schema_table(table_schema,table_name,table_comment,table_rows,data_size,create_time,update_time) values (table_schema_1,table_name_1,table_comment_1,table_rows_1,data_size_1,create_time_1,update_time_1);
  end while;

	#关闭游标
	close sql_schema_table;
	
#存储过程执行代码的结尾
end //
#改变语句结束符为;。是将语句结束符改回;。
DELIMITER ;
call name_sql_date('数据库名');

 运行存储过程后,发现报错1329 - No data - zero rows fetched, selected, or processed。

但去查看结果存放表(schema_table)时发现,表里已经有数据了。这是因为while true循环导致的。这个问题用条件处理(捕捉异常并处理)解决。详见目录第10点(下一章节)。

2)样例2

根据传入的数据库名,查询该数据库所有表的信息,并插入对应的结果存放表中。然后再统计准确的数据量更新到结果存放表中。

定义变量:先定义需要字段的变量,用于后面游标获取数据后进行赋值。

声明游标:游标用来查询传入的数据库名的数据库表的信息。并对游标循环结束后进行变量赋值。

建表入表:建一个结果存放表。并且将要查询的库表原始信息放入结果存放表,用于每次执行都是新的数据。

打开游标:使用游标前,要先打开游标。等

循环处理:使用游标获取数据,将查询到的数据更新到结果存放表。

关闭游标:循环处理结束后,进行关闭游标

#改变语句结束符为//。
DELIMITER //
#创建存储过程名称([ 参数列表 ])。参数列表可以为空。不需要参数的可把参数去了
create procedure name_sql_date_rows(IN nname varchar(25))

#存储过程执行代码的开头
begin 
	#定义变量
   DECLARE s int DEFAULT 0;
   DECLARE table_schema_1 varchar(256);
   DECLARE table_name_1 varchar(256);
	
	#声明游标
	declare sql_schema_table cursor for select table_schema,table_name from schema_table_rows;
	
	#声明当游标循环完后,将标志变量置成某个值
   DECLARE CONTINUE HANDLER FOR NOT FOUND SET s=1;
	
	#创建结果存放表。
create table if not exists `schema_table_rows`  (
  `id` int(25) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `table_schema` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '数据库名称',
  `table_name` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表英文名称',
  `table_comment` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表中文名称',
  `table_rows` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '数据行数',
  `data_size` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表大小',
  `create_time` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表创建时间',
  `update_time` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表更新时间',
  `TONG_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '入库时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 19246 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '数据库-数据表相关信息' ROW_FORMAT = Dynamic;
	
	
	#插入结果存放表的原始数据
	insert into  schema_table_rows(table_schema
	,table_name
	,table_comment
	,table_rows
	,data_size
	,create_time
	,update_time
	)
	SELECT 
	a.table_schema,
	a.table_name,
	a.table_comment,
	a.table_rows,
	( a.data_length / 1024 ) AS data_size,
	a.create_time,
	a.update_time 
	FROM
	information_schema.`tables` a
	left join schema_table_rows b  on  a.table_schema = b.table_schema and a.table_name = b.table_name
	where b.table_name is null  and a.table_name <> 'schema_table_rows' and a.table_schema = nname;   
	
	#打开游标
	open sql_schema_table;
	
	#循环,true表示循环所有
  while s <> 1 do
		#游标获取数据,并进行赋值。
        fetch sql_schema_table into table_schema_1,table_name_1;
		#将查询到的数据更新到结果存放表
		#定义变量
   set @rows_sql =CONCAT("update schema_table_rows  set table_rows = (select count(1) from ",table_schema_1,'.',table_name_1,") where table_schema='",table_schema_1,"' and table_name='",table_name_1,"' ");
	 
	  #使用PREPARE语句,将@rows_sql的内容,准备为一个可执行的语句。
		PREPARE update_rows FROM @rows_sql;
	  
		#使用EXECUTE语句执行准备好的语句。
		EXECUTE update_rows ;
		
		#循环完成后,s会被赋值为1,然后退出循环。这个上面头有做赋值声明。
  end while;

	#关闭游标
	close sql_schema_table;
	
	#释放准备好的语句连接。
	DEALLOCATE PREPARE update_rows; 
	
	
#存储过程执行代码的结尾
end //
#改变语句结束符为;。是将语句结束符改回;。
DELIMITER ;
call name_sql_date_rows('ling');

10、条件处理(捕捉异常并处理)

1.语法格式:

DECLARE handler_name HANDLER FOR condition_value  action_statement

#中文注释
DECLARE 异常处理选项  HANDLER FOR    捕获的异常      异常发生时执行的语句

#样例
#        异常处理选项                  捕获的异常           异常发生时执行的语句
declare    exit        handler for   not found          close sql_schema_table;
declare    exit        handler for   SQLSTATE '02000'   close sql_schema_table;

1、handler_name 表示异常处理程序的名称,重要取值包括:
CONTINUE:发生异常后,继续执行存储过程。(捕捉)
EXIT:发生异常后,终止存储过程的执行。(上抛)


2、condition_value 是指捕获的异常:
        SQLSTATE sqlstate_value,sqlstate_value是指状态码,样例:SQLSTATE ‘02000’。

        也可以用下面的代码简写:
        SQLWARNING,代表所有01开头的SQLSTATE,01是指警告的报错信息。
        NOT  FOUND,代表所有02开头的SQLSTATE,02是指无数据的报错信息。
        SQLEXCEPTION,除了01和02开头的所有SQLSTATE。


3、action_statement 是指异常发生时执行的语句,例如:CLOSE sql_schema_table

2.语句样例

 1)样例1

根据传入的数据库名,查询该数据库所有表的信息,并插入对应的结果存放表中。

定义变量:先定义需要字段的变量,用于后面游标获取数据后进行赋值。

声明游标:游标用来查询传入的数据库名的数据库所有表的信息。

条件处理:根据前面执行的报错信息,添加对应的条件处理。

建表清表:建一个结果存放表。并且清空下结果存放表,用于每次执行都是新的数据。

打开游标:使用游标前,要先打开游标。

循环处理:使用游标获取数据,并进行处理。

关闭游标:循环处理结束后,进行关闭游标。

#改变语句结束符为//。
DELIMITER //
#创建存储过程名称([ 参数列表 ])。参数列表可以为空。不需要参数的可把参数去了
create procedure name_sql_date(IN nname varchar(25))

#存储过程执行代码的开头
begin 
	#定义变量
	DECLARE table_schema_1 varchar(255);
	DECLARE table_name_1 varchar(255);
	DECLARE table_comment_1 varchar(255);
	DECLARE table_rows_1 varchar(255);
	DECLARE data_size_1 varchar(255);
	DECLARE create_time_1 varchar(255);
	DECLARE update_time_1 varchar(255);
	
	#声明游标
	declare sql_schema_table cursor for select table_schema,table_name,table_comment,table_rows,( data_length / 1024 ) as data_size,create_time,update_time from information_schema.`tables` where  table_schema = nname;
	
    #条件处理
	declare exit handler for not found close sql_schema_table;

	#创建结果存放表,字段顺序与上面查询语句的字段顺序一样
	    create table if not exists `schema_table` (
        `table_schema` VARCHAR ( 255 ) DEFAULT NULL COMMENT '数据库名称',
        `table_name` VARCHAR ( 257 ) DEFAULT NULL COMMENT '表英文名称',
        `table_comment` VARCHAR ( 258 ) DEFAULT NULL COMMENT '表中文名称',
        `table_rows` VARCHAR ( 259 ) DEFAULT NULL COMMENT '数据行数',
        `data_size` VARCHAR ( 260 ) DEFAULT NULL COMMENT '表大小',
        `create_time` VARCHAR ( 261 ) DEFAULT NULL COMMENT '创建时间',
        `update_time` VARCHAR ( 262 ) DEFAULT NULL COMMENT '更新时间'
    ) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT = '数据库-数据表相关信息';
	
	#清空结果存放表
	truncate table schema_table;
	
	#打开游标
	open sql_schema_table;
	
	#循环,true表示循环所有
  while true do
		#游标获取数据,并进行赋值。
        fetch sql_schema_table into table_schema_1,table_name_1,table_comment_1,table_rows_1,data_size_1,create_time_1,update_time_1;
		#将得到的数据进行插入结果存放表
        insert into schema_table(table_schema,table_name,table_comment,table_rows,data_size,create_time,update_time) values (table_schema_1,table_name_1,table_comment_1,table_rows_1,data_size_1,create_time_1,update_time_1);
  end while;

	#关闭游标
	close sql_schema_table;
	
#存储过程执行代码的结尾
end //
#改变语句结束符为;。是将语句结束符改回;。
DELIMITER ;
call name_sql_date('数据库名');

如果没加条件处理,运行存储过程后,会发现报错1329 - No data - zero rows fetched, selected, or processed。加条件处理后,能顺利执行无报错。