MySQL进阶篇之存储过程(procedure)

这篇具有很好参考价值的文章主要介绍了MySQL进阶篇之存储过程(procedure)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

04、视图/存储过程/触发器

4.1、视图(view)

4.2、存储过程(procedure)

4.2.1、介绍

1、介绍

存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。

存储过程思想上很简单,就是数据库SQL语言层面的代码封装与重用。

2、特点

  • 封装、复用
  • 可以接收参数,也可以返回数据
  • 减少网络交互,效率提升
4.2.2、基本语法

1、基本语法

  • 创建

    CREATE PROCEDURE 存储过程名称([参数列表])
    BEGIN
       -- SQL语句
    END;
    
  • 调用

    CALL 存储过程名称([参数]);
    
  • 查看

    -- 查询指定数据库的存储过程及状态信息
    SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = '数据库名称';
    
    -- 查询整个存储过程的定义
    SHOW CREATE PROCEDURE 存储过程名称;
    
  • 删除

    DROP PROCEDURE [IF EXISTS] 存储过程名称;
    

2、演示:

-- 存储过程基本语法
-- 创建
create procedure p1()
begin
  select count(*) from student;
end$$

-- 调用
call p1();

-- 查看
select * from information_schema.ROUTINES where ROUTINE_SCHEMA = 'itcast';
show create procedure p1;

-- 删除
drop procedure if exists p1;

注意

在命令行中,执行创建存储过程的SQL时,需要通过关键字delimiter指定SQL语句的结束符。

mysql procedure,MySQL学习笔记(黑马程序员),mysql,数据库,sql

4.2.3、变量
4.2.3.1、系统变量

1、介绍

系统变量时MySQL服务器提供,不是用户定义的,属于服务器层面。

可分为:全局变量(GLOBAL)、会话变量(SESSION)。

全局变量在所有会话中有效,会话变量仅在当前会话中有效。

2、语法:

  • 查看系统变量

    -- 查看所有系统变量
    SHOW [SESSION | GLOBAL] VARIABLES;
    
    -- 可以通过like模糊匹配方式查找变量
    SHOW [SESSION | GLOBAL] VARIABLES LIKE '...';
    
    -- 查看指定变量的值
    SELECT @@[SESSION. | GLOBAL.] 系统变量名;
    
  • 设置系统变量

    SET [SESSION | GLOBAL] 系统变量名 = 值;
    SET @@[SESSION. | GLOBAL.]系统变量名 = 值;
    

3、演示:

-- 变量:系统变量
-- 查看系统变量
show session variables;
show session variables like 'auto%';
show global variables like 'auto%';
select @@global.autocommit;

-- 设置系统变量
set session autocommit = 1;
set global autocommit = 1;
set @@global.autocommit = 1;

注意

  • 如果没有指定SESSION/GLOBAL,默认是SESSION,会话变量。
  • mysql服务重新启动之后,所设置的全局参数会失效,要想不失效,可以在/etc/my.cnf中设置。
4.2.3.2、用户定义变量

1、介绍

用户定义变量是用户根据需要自己定义的变量,用户变量不用提前声明,在用的时候直接用“@变量名”使用就可以。其作用域为当前连接(会话)。

2、语法:

  • 赋值

    SET @var_name = expr[, @var_name = expr] ...;
    SET @var_name := expr[, @var_name := expr] ...;
    
    SELECT @var_name := expr[, @var_name := expr] ...;
    SELECT 字段名 INTO @var_name FROM 表名;
    
  • 使用

    SELECT @var_name;
    

3、演示:

-- 变量:用户定义变量
-- 赋值
set @myname = 'itcast';
set @myage := 10;
set @mygender := '女', @myhobby := 'mysql';

select @mycolor := 'red';
select count(*) into @mycount from tb_user;

-- 使用
select @myname, @myage, @mygender;

select @mycolor, @mycount;

注意

用户定义的变量无需对其进行声明或初始化,只不过获取的值为NULL。

mysql procedure,MySQL学习笔记(黑马程序员),mysql,数据库,sql

4.2.3.3、局部变量

1、介绍

局部变量是根据需要定义的在局部生效的变量,访问之前,需要DECLARE声明。可用作存储过程内的局部变量和输入参数,局部变量的范围是在其内声明的BEGIN ... END块。

2、语法

  • 声明

    DECLARE 变量名 变量类型 [DEFAULT ...];
    

    变量类型就是数据库字段类型:INTBIGINTCHARVARCAHRDATETIME等。

  • 赋值

    SET 变量名 = 值;
    SET 变量名 := 值;
    SELECT 字段名 INTO 变量名 FROM 表名 ...;
    

3、演示:

-- 变量:局部变量

create procedure p2()
begin
  -- 声明 -- declare
  declare stu_count int default 0;
	
	-- 赋值
	-- set stu_count := 100;
	select count(*) into stu_count from student;
	
	select stu_count;
end;

call p2();

4.2.4、if判断

1、语法:

IF 条件1 THEN
  ...
ELSEIF 条件2 THEN    -- 可选
  ...
ELSE                -- 可选
  ...
END IF;

2、定义存储过程,完成如下需求:

根据定义的分数score变量,判断当前分数对应的分数等级。

  • score >= 85分,等级为优秀;
  • score >= 60分,且score < 85分,等级为及格;
  • score < 60分,等级为不及格。
-- 创建存储过程
create procedure grade_score() 
begin
  declare score int default 58;
  declare grade varchar(10);
  
  if score >= 85 then
     set grade := '优秀';
  elseif score >= 60 then
     set grade := '及格';
  else
     set grade := '不及格';
  end if;
  
  select grade;
end;

-- 调用
call grade_score();
4.2.5、参数(IN/OUT/INOUT)

1、参数

类型 含义 备注
IN 该类参数作为输入,也就是需要调用时传入值 默认
OUT 该类参数作为输出,也就是该参数可以作为返回值
INOUT 既可以作为输入参数,也可以作为输出参数

2、语法

CREATE PROCEDURE 存储过程名称([IN/OUT/INOUT 参数名 参数类型])
BEGIN
  -- SQL语句
END;

3、定义存储过程,完成如下需求:

① 根据传入参数score,判断当前分数对应的分数等级,并返回

  • score >= 85分,等级为优秀;
  • score >= 60分,且score < 85分,等级为及格;
  • score < 60分,等级为不及格。
-- 创建存储过程
create procedure grade_core_2(in score int, out grade varchar(10))
begin
  if score >= 85 then
     set grade := '优秀';
  elseif score >= 60 then
     set grade := '及格';
  else
     set grade := '不及格';
  end if;
  
  select grade;
end;

-- 调用 
call grade_core_2(18, @result);
select @result; 

② 将传入的200分制的分数,换算成百分制,然后返回分数。

-- 创建存储过程
create procedure p3(inout score double) 
begin
  set score := score / 2;
end;

-- 调用
set @score := 78;  -- 先给变量赋值
call p3(@score);   -- 调用存储过程,将78传入,并将结果输出赋值给score
select @score;     -- 查询展示结果
4.2.6、case

1、语法

  • 语法一:

    CASE case_value
         WHEN when_value1 THEN statement_list1
         [WHEN when_value2 THEN statement_list2]...
         [ELSE statement_list]
    END CASE;
    
  • 语法二:

    CASE
         WHEN search_condition1 WHEN statement_list1
         [WHEN search_condition2 WHEN statement_list2]...
         [ELSE statement_list]
    END CASE;
    

2、定义存储过程,完成如下需求:

根据传入的月份,判断月份所属的季度(要求采用case结构)

  • 1-3月份,为第一季度
  • 4-6月份,为第二季度
  • 7-9月份,为第三季度
  • 10-12月份,为第四季度
-- 创建存储过程
create procedure p6(in month int)
begin
  declare result varchar(10);
  
  case
    when month >= 1 and month <= 3 then
      set result := '第一季度';
    when month >= 4 and month <= 6 then
      set result := '第二季度';
    when month >= 7 and month <= 9 then
      set result := '第三季度';
    when month >= 10 and month <= 12 then
      set result := '第四季度';
    else 
      set result := '非法传输';
  end case;
  
  select concat('您输入的月份为:',month,",所属的季度为:",result);
end;

-- 调用
call p6(8);
4.2.7、循环
4.2.7.1、while

1、while循环是有条件的循环控制语句。满足条件后,再执行循环体中的SQL语句。具体语法为:

# 先判定条件,如果条件为true,则执行逻辑,否则,不执行逻辑
WHILE 条件 DO
   SQL逻辑...
END WHILE;

2、定义存储过程,完成如下需求

计算从1累加到n的值,n为传入的参数值。文章来源地址https://www.toymoban.com/news/detail-788091.html

-- A.定义局部变量,记录累加之后的值
-- B.每循环一次,就会对n进行减1,如果n减到0,则退出循环

create procedure p7(in n int) 
begin
  declare total int default 0;
  
  while n > 0 do 
     set total := total + n;
     set n := n - 1;
  end while;
	
	select total;
end;

-- 调用
call p7(100);
4.2.7.2、repeat

1、repeat是有条件的循环控制语句,当满足条件的时候退出循环。具体语法为:

# 先执行一次逻辑,然后判定逻辑是否满足,如果满足,则退出。如果不满足,则继续下一次循环
REPEAT 
   SQL逻辑...
UNTIL 条件
END REPEAT;

2、定义存储过程,完成如下需求

计算从1累加到n的值,n为传入的参数值。

-- A.定义局部变量,记录累加之后的值
-- B.每循环一次,就会对n进行减1,如果n减到0,则退出循环

create procedure p8(in n int) 
begin
  declare total int default 0;
  
  repeat 
     set total := total + n;
     set n := n - 1;
  until n <= 0
  end repeat;
	
	select total;
end;

-- 调用
call p8(100);
4.2.7.3、loop

1、LOOP实现简单的循环,如果不在SQL逻辑中增加退出循环的条件,可以用其来实现简单的死循环。

LOOP可以配合以下两个语句使用:

  • LEAVE:配合循环使用,退出循环。
  • ITERATE:必须用在循环中,作用是跳过当前循环剩下的语句,直接进入下一次循环。

2、语法:

[begin_label:] LOOP
   SQL逻辑...
END LOOP [end_label];
-- 退出指定标记的循环体
LEAVE label;

-- 直接进入下一次循环
ITERATE label;

3、定义存储过程,完成如下需求

① 计算从1累加到n的值,n为传入的参数值。

-- loop
-- A.定义局部变量,记录累加之后的值
-- B.每循环一次,就会对n进行减1,如果n减到0,则退出循环
create procedure p9(in n int)
begin
   declare total int default 0;
  
   sum:loop
	   if n <= 0 then 
		    leave sum;
	   end if;
		 
	   set total := total + n;
       set n := n - 1;
	end loop sum;
	
	select total;
end;

-- 调用
call p9(100);

② 计算从1到n之间的偶数累加的值,n为传入的参数值。

-- A. 定义局部变量, 记录累加之后的值;
-- B. 每循环一次, 就会对n进行-1 , 如果n减到0, 则退出循环 ----> leave xx
-- C. 如果当次累加的数据是奇数, 则直接进入下一次循环. --------> iterate xx
 
create procedure p10(in n int)
begin
    declare total int default 0;
 
    sum:loop
        if n<=0 then
            leave sum;
        end if;
 
        if n%2 = 1 then
            set n := n - 1;
            iterate sum;
        end if;
 
        set total := total + n;
        set n := n - 1;
    end loop sum;
 
    select total;
end;
 
-- 调用
call p10(100);
4.2.8、游标

1、介绍

游标(cursor)是用来存储查询结果集的数据类型,在存储过程和函数中可以使用游标对结果集进行循环的处理。

2、游标的使用包括游标的声明、OPENFETCHCLOSE,其语法分别如下:

  • 声明游标

    DECLARE 游标名称 CURSOR FOR 查询语句;
    
  • 打开游标

    OPEN 游标名称;
    
  • 获取游标记录

    FETCH 游标名称 INTO 变量[,变量];
    
  • 关闭游标

    CLOSE 游标名称;
    

3、定义存储过程,完成如下需求

根据传入的参数uage,来查询用户表tb_user中,所有用户年龄小于等于uage的用户姓名(name)和专业(profession),并将用户的姓名和专业插入到所创建的一张新表(id,name,profession)中。

-- 逻辑实现
-- A.声明游标,存储查询结果集
-- B.准备:创建表结构
-- C.开启游标
-- D.循环获取游标中的记录
-- E.插入数据到新表中
-- F.关闭游标

create procedure p11(in uage int)
begin
  declare uname varchar(100);
	declare uprofession varchar(100);
	declare u_cursor cursor for select name,profession from tb_user where age <= uage;
	
	drop table if exists tb_user_pro;
	create table if not exists tb_user_pro(
			id int primary key auto_increment,
			name varchar(100),
			profession varchar(100)
	);
	
	open u_cursor;
	
	while true do
			fetch u_cursor into uname, uprofession;
			insert into tb_user_pro values(null, uname, uprofession);
	end while;
	
	close u_cursor;
end;

-- 调用
call p11(40);

注意:声明变量在声明游标之前

调用存储过程p11(),报错:

mysql procedure,MySQL学习笔记(黑马程序员),mysql,数据库,sql

上述的功能,虽然我们实现了,但是逻辑并不完善,而且程序执行完毕,获取不到数据,数据库还报错。 接下来,我们就需要来完成这个存储过程,并且解决这个问题。

要想解决这个问题,就需要通过MySQL中提供的条件处理程序Handler来解决。

4.2.9、条件处理程序(handler)

1、介绍

条件处理程序(Handler)可以用来定义在流程控制结构执行过程中遇到问题时相应的处理步骤。

2、语法:

DECLARE handler_action HANDLER FOR condition_value[,condition_value]... statement;
  • handler_action
    • CONTINUE:继续执行当前程序
    • EXIT:终止执行当前程序
  • condition_value
    • SQLSTATE sqlstate_value:状态码,如02000
      • SQLWARNING:所有以01开头的SQLSTATE代码的简写
      • NOT FOUND:所有以02开头的SQLSTATE代码的简写
      • SQLEXCEPTION:所有没有被SQLWARNING或NOT FOUND捕获的SQLSTATE代码的简写

状态码可查看:https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html

3、案例

解决上一节的问题:

create procedure p11(in uage int)
begin
  declare uname varchar(100);
	declare uprofession varchar(100);
	declare u_cursor cursor for select name,profession from tb_user where age <= uage;
	-- declare exit handler for SQLSTATE '02000' close u_cursor;
	declare exit handler for not found close u_cursor;
	
	drop table if exists tb_user_pro;
	create table if not exists tb_user_pro(
			id int primary key auto_increment,
			name varchar(100),
			profession varchar(100)
	);
	
	open u_cursor;
	
	while true do
			fetch u_cursor into uname, uprofession;
			insert into tb_user_pro values(null, uname, uprofession);
	end while;
	
	close u_cursor;
end;

call p11(40);
4.2.10、存储函数

1、介绍

存储函数是有返回值的存储过程,存储函数的参数只能是IN类型的。

2、语法:

CREATE FUNCTION 存储函数名称([参数列表])
RETURNS type [characteristics ...]
BEGIN
	-- SQL语句
	RETURN ...;
END;

characteristics的说明:

  • DETERMINISTIC:相同的输入参数总是产生相同的结果
  • NO SQL:不包含SQL语句
  • READS SQL DATA:包含读取数据的语句,但不包含写入数据的语句。

3、定义存储函数,完成如下需求

计算从1累加到n的值,n为传入的参数值。

-- 存储函数
-- 从1到n的累加
create function fun1(n int) 
returns int deterministic
begin
	declare total int default 0;
	
	while n > 0 do
		set total := total + n;
		set n := n - 1;
	end while;
	
	return total;
end;

-- 调用存储函数,并显示结果
select fun1(100);

4.3、触发器(trigger)

到了这里,关于MySQL进阶篇之存储过程(procedure)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【MySql】MySql存储过程与函数

    存储过程没有返回值,函数有返回值 存储过程就是一组预先编译好的SQL语句的封装,需要执行时客户端向服务器发送调用请求,服务器就会将这一系列预先存储好的SQL语句全部执行。 简单举例:存储过程的创建 DELIMITER意味将$设置为结束标识,这样就可以在存储过程中使用分

    2024年02月09日
    浏览(35)
  • Mysql 存储过程 / 存储函数

    目录 0 课程视频 1 基本语法 1.0 作用 -在数据库中 封装sql语句 - 复用 - 减少网络交互 -可接收参数返回数据 1.1 创建 1.2 调用 1.3 查看 1.4 删除 1.5 ; 封号结束符 改成 $$ 双刀符合结束语句 - 因为打包封号结束有冲突 1.6 在cmd 中定义 存储过程 打包的事务 - 打包完 可以改回 封号  

    2024年02月01日
    浏览(40)
  • MySQL(视图,存储函数,存储过程)

    作业1:  作业实现: 首先创建学生表,课程表,以及学生选课表。  1.用SQL语句创建学生表student,定义主键,姓名不能重名,性别只能输入男或女,所在系的默认值是 “计算机”。 2.修改student 表中年龄(age)字段属性,数据类型由int 改变为smallint。 3.为SC表建立按学号(

    2024年01月21日
    浏览(33)
  • MySQL——存储过程与存储函数

    MySQL从 5.0版本 开始支持 存储过程 和 存储函数 。存储过程和函数能够将复杂的SQL逻辑封装在一起,应用程序无须关注存储过程和函数内部复杂的SQL逻辑,而只需要简单地调用存储过程和函数即可。 1.1 理解 含义 :存储过程的英文是 Stored Procedure 。它的思想很简单,就是一组

    2024年02月10日
    浏览(31)
  • MySQL-09-mysql 存储过程入门介绍

    MySQL 00 View MySQL 01 Ruler mysql 日常开发规范 MySQL 02 truncate table 与 delete 清空表的区别和坑 MySQL 03 Expression 1 of ORDER BY clause is not in SELECT list,references column MySQL 04 EMOJI 表情与 UTF8MB4 的故事 MySQL 05 MySQL入门教程(MySQL tutorial book) MySQL 06 mysql 如何实现类似 oracle 的 merge into MySQL 07 timeo

    2024年04月13日
    浏览(26)
  • Mysql高阶语句与MySQL存储过程

    准备环境 1、select 显示表格中一个或数个字段的所有资料 语法:select 字段 from 表名 select region from store_info; 2、distinct 不显示重复的数据记录 语法:select distinct ‘字段’ from ‘表名’; select distinct storm_name from store_info ; 3、where 有条件查询 语法:select “字段” from\\\"表名\\\" wher

    2024年02月13日
    浏览(31)
  • MySQL存储函数与存储过程习题

    创建表并插入数据: 1、创建一个可以统计表格内记录条数的存储函数 ,函数名为count_sch() 先创建一个表并插入一些数据: mysql d // mysql create function count_sch() - returns int - begin - declare i int default 0; - select count(*) into i from sch; - return i; - end // Query OK, 0 rows affected (0.00 sec) mysql sel

    2024年01月19日
    浏览(39)
  • MySQL之存储过程和存储函数

    能够将完成特定功能的SQL指令进行封装(SQL指令集),编译之后存储在数据库服务器上,并且为之取一个名字,客户端可以通过名字直接调用这个SQL指令集,获取执行结果。 2.1 优点 (1)SQL指令无需经客户端编写通过网络传送,可以节省网络开销,同时避免使用SQL指令在网络传

    2024年02月05日
    浏览(40)
  • MySQL 存储过程和函数

    目录 一、存储过程和函数概述 二、创建存储过程和函数 1、创建存储过程 2、创建存储函数 三、查看/调用储存过程和函数 1、查看储存过程/函数 2、调用储存过程/函数 四、修改/删除存储过程和函数 1、修改存储过程和函数 2、删除存储过程和函数 五、练习  存储过程就是一

    2024年02月11日
    浏览(25)
  • MySQL存储过程(二十四)

    你相信吗, 相信那一天的夕阳吗? 上一章简单介绍了 MySQL的索引(二十三),如果没有看过,请观看上一章 MySQL从5.0版本开始支持存储过程和函数。存储过程和函数能够将复杂的SQL逻辑封装在一起, 应用程序无须关注存储过程和函数内部复杂的SQL逻辑, 而只需要简单地调用存储过

    2024年02月14日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包