mysql 存储过程使用收藏

整理收藏存储过程相关语法和样例,方便后续使用;

【创建存储过程】

语法结构:

CREATE PROCEDURE <过程名>(参数列表 参数类型)
BEGIN
	<过程体 sql语句>
END

使用样例:

-- 1、创建存储过程
-- 返回为列表多条记录,但无外围接收变量,个人感觉无意见
drop PROCEDURE IF EXISTS getUserList;
-- 注1: 在mysql v5.7版本使用if not exists报错,在v8.0版本无问题; CREATE PROCEDURE if not exists getUserList ()
CREATE PROCEDURE getUserList ()
 BEGIN
  SELECT id, username, `password` FROM user ORDER BY score DESC LIMIT 20;
END;

-- 调用
call getUserList();
【删除存储过程】

语法结构:

DROP PROCEDURE 过程名;           #删除的时候不要加小括号,直接给定存储过程的名字即可
DROP PROCEDURE IF EXISTS 过程名; #如果存储删除,不存在不删除并且不会报错

使用样例:

-- 2、删除存储过程
-- 如果存在即删除存储过程
drop PROCEDURE IF EXISTS getUserList;
【调用存储过程】

语法结构:

CALL 过程名();

使用样例:

-- 3、调用存储过程(这里返回的是列表多条记录)
call test.getUserList();
【查看存储过程】
# 查询存储过程的状态信息
show procedure status;  

# 查询指定数据库中的所有的存储过程
select name from mysql.proc where db='test'; 

 # 根据存储过程名称查询 
SELECT name from mysql.proc where name like '%calculate%'
【变量声明和赋值】

语法结构:

DECLARE 变量名[,...] type [DEFAULT value]

使用样例:

-- 5、变量的声明和赋值
drop PROCEDURE calculate;
CREATE PROCEDURE calculate ()
BEGIN
 DECLARE num1 INT;
 DECLARE num2 INT DEFAULT 1;
 SELECT num1 + num2;
 #SELECT num1 * num2;
 #SELECT num2 - num1;
END
call calculate(); 
#num1是没有默认值的,所以SELECT num1 + num2; 是一个null值; 
#如赋值为给num1=0,返回值是1;
#如将“num1 + num2;”修改为“num1 * num2;”返回为0;
#如将"num1 + num2;"修改为"num2 - num1;"返回为null;
#表示如果声明变量不设置默认值,它与任何变量做基本运算返回将为null值;
变量赋值(SET)

注意:一次可以给多个变量赋值,中间使用逗号隔开。
语法结构:

SET 变量名 = 变量值 [,变量名 = 变量值] ...

使用样例:

-- 变量的赋值
CREATE PROCEDURE calculate2 ()
BEGIN
 DECLARE num1 INT;
 DECLARE num2 INT DEFAULT 1;
 SET num1=2, num2=3;
 SELECT num1 + num2;
END
call calculate2(); # 5
变量赋值(SELECT INTO)

语法结构:

SELECT <column | 聚合函数> INTO 变量名;

使用样例:

-- INTO赋值
 CREATE PROCEDURE calculate3 ()
 BEGIN
  DECLARE num1 INT;
  DECLARE num2 INT DEFAULT 1;
  SELECT count(1) INTO num1 FROM user;
  SELECT num1+num2;
 END
 
call calculate3(); # 8
条件判断(IF)

语法格式:

# 只有满足差选条件才会执行 then 后面的SQL语句
if search_condition(查询条件) then statement_list(SQL语句)
    [else if search_condition(查询条件) then statement_list(SQL语句)]...
    [else statement_list(SQL语句)]
end if;

使用样例:

-- if条件判断
 drop PROCEDURE if EXISTS calculate4;
 CREATE PROCEDURE calculate4 (IN uid INT(11))
 BEGIN
  DECLARE scoreStatus VARCHAR(20);
  DECLARE scoreValue INT(11);
  SELECT score INTO scoreValue FROM user WHERE id=uid LIMIT 1;
  IF scoreValue >= 90 THEN
   SET scoreStatus='成绩【优】';
  ELSEIF scoreValue >=80 THEN
    SET scoreStatus='成绩【良】';
  ELSEIF scoreValue >=60 THEN
    set scoreStatus ='成绩【中】'; 
  ELSE
   SET scoreStatus ='成绩【差】';
  END IF;
  SELECT scoreStatus;
 END
 call calculate4(4);
传递参数(in/out/inout)

语法格式:

CREATE PROCEDURE <过程名>([in/out/inout] 参数列表 参数类型)
BEGIN
	<过程体 sql语句>
END
  1. in : 该参数可以作为输入,调用该存储过程需要传入的值,默认的选项
  2. out : 该参数作为输出,调用该存储过程之后返回的值。
  3. inout : 既可以作为输入参数也可以作为输出参数
in
-- in : 该参数可以作为输入,调用该存储过程需要传入的值,否则返回默认值
 drop PROCEDURE if EXISTS calculate5;
 CREATE PROCEDURE calculate5 (IN scoreValue INT(11))
 BEGIN
  DECLARE scoreStatus VARCHAR(20);
  IF scoreValue >= 90 THEN
   SET scoreStatus='成绩【优】';
  ELSEIF scoreValue >=80 THEN
    SET scoreStatus='成绩【良】';
  ELSEIF scoreValue >=60 THEN
    set scoreStatus ='成绩【中】'; 
  ELSE
   SET scoreStatus ='成绩【差】';
  END IF;
  SELECT scoreStatus;
 END
 
call calculate5(80);
out
-- out : 该参数作为输出,调用该存储过程之后返回的值。
drop PROCEDURE if EXISTS calculate6;
CREATE PROCEDURE calculate6 (IN scoreValue INT(11), OUT scoreStatus varchar(20))
BEGIN
 IF scoreValue >= 90 THEN
  SET scoreStatus='成绩【优】';
 ELSEIF scoreValue >=80 THEN
   SET scoreStatus='成绩【良】';
 ELSEIF scoreValue >=60 THEN
   set scoreStatus ='成绩【中】'; 
 ELSE
  SET scoreStatus ='成绩【差】';
 END IF;
 SELECT scoreStatus;
END

call calculate6(0, @scoreStatus);
SELECT @scoreStatus;
inout
-- inout : 既可以作为输入参数也可以作为输出参数
drop PROCEDURE if EXISTS calculate6;
CREATE PROCEDURE calculate6 (INOUT inoutStr varchar(20))
BEGIN
 IF inoutStr='优'  THEN
  SET inoutStr='成绩【优】';
 ELSEIF inoutStr='良' THEN
   SET inoutStr='成绩【良】';
 ELSEIF inoutStr='中' THEN
   set inoutStr ='成绩【中】'; 
 ELSE
  SET inoutStr ='成绩【差】';
 END IF;
 SELECT inoutStr;
END

set @inoutStr="优";
call calculate6(@inoutStr);
SELECT @inoutStr as inoutStrValue;
修改和获取系统变量
-- @@global : 这种在变量名前加上 “@@” 符号,叫做系统变量。
-- 通过@@修改和获取系统变量
-- 1、读取最大链接数 
 SELECT @@max_connections;
-- 2、更新最大链数 
 SET GLOBAL max_connections = 100;
case结构

语法格式:

# 方式一
case case_value(判断的值)
    when when_value(比较的值) then statement_list(SQL语句)
    [when when_value(比较的值) then statement_list(SQL语句)]...
    [else statement_list(SQL语句)]
end case;# 方式二
case 
    when search_condition(查询条件) then statement_list(SQL语句)
    [when search_condition(查询条件) then statement_list(SQL语句)]...
    [else statement_list(SQL语句)]
end case;

使用样例(方式一):

drop PROCEDURE if EXISTS calculate71;
CREATE PROCEDURE calculate71 (IN scoreValue INT(11), OUT scoreStatus VARCHAR(20))
BEGIN
 CASE scoreValue != null && scoreValue > 100
	 WHEN scoreValue >= 90 THEN
		SET scoreStatus='成绩【优】';
	 WHEN scoreValue >= 80 THEN
		SET scoreStatus='成绩【良】';
	 WHEN scoreValue >= 60 THEN
		SET scoreStatus='成绩【中】';
	 WHEN scoreValue>=1 THEN 
	  SET scoreStatus='成绩【差】';
	 ELSE
		SET scoreStatus='成绩数据异常';
 END CASE;
END

set @scoreStatus = '暂无';
call calculate71(150, @scoreStatus);
SELECT @scoreStatus as scoreStatusVal;

使用样例(方式二):

drop PROCEDURE if EXISTS calculate7;
CREATE PROCEDURE calculate7 (IN scoreValue INT(11), OUT scoreStatus VARCHAR(20))
BEGIN
 CASE 
 WHEN scoreValue >= 90 THEN
  SET scoreStatus='成绩【优】';
 WHEN scoreValue >= 80 THEN
  SET scoreStatus='成绩【良】';
 WHEN scoreValue >= 60 THEN
  SET scoreStatus='成绩【中】';
 ELSE
  SET scoreStatus='成绩【差】';
 END CASE;
END

set @scoreStatus = '暂无';
call calculate7(null, @scoreStatus);
SELECT @scoreStatus as scoreStatusVal;
while循环

语法结构:

# 只要查询条件一直成立就会一直指定do后面的SQL语句,当查询条件不成立的时候直接跳出while循环
while search_condition(查询条件) do
    statement_list(SQL语句)
end while;

使用样例:

-- while结构
-- 需求:获取指定数内奇数的累计值
drop PROCEDURE IF EXISTS calculate8;
CREATE PROCEDURE calculate8 (IN num INT(11))
BEGIN
 DECLARE number INT DEFAULT 0;
 DECLARE total INT DEFAULT 0;

 WHILE number <= num DO
   IF number % 2 = 0 THEN
		 SET total = total + number;
   END IF;
	 SET number = number + 1;
 END WHILE;
 
 SELECT total;
END

call calculate8(10);
repeat循环

语法格式:

repeat 
    statement_list(SQL语句)
    until search_condition(查询添加)
end repeat;

使用样例:

drop PROCEDURE calculate9;
CREATE PROCEDURE calculate9 (IN num INT(11))
BEGIN
 DECLARE total INT DEFAULT 0;
 REPEAT 
    set total = total + num;
    set num = num - 1;
    # 注意:这个 unti 后的查询条件不要加分号,加分号会报错。
    until num = 0
  END REPEAT;
 SELECT total;
END
call calculate9(10); 
-- call calculate9(0); #注:这里如果传值为0,会一直执行,并没有调出循环,不知是否为使用或语法问题 
loop循环与leave语句

语法结构:

[begin_label:] loop
    statement_list
end loop [end_label]
  • loop:实现简单的循环,退出循环的条件需要使用其他的语句定义,通常可以使用leave语句实现,
  • 如果不在statement_list中增加退出循环的语句,那么loop语句可以永安里实现简单的死循环。
  • leave:用来从标注的流程构造中退出,通常和 begin…end 或循环一起使用。
 CREATE PROCEDURE calculate10 (IN num INT(11))
 BEGIN
 	DECLARE total INT DEFAULT 0;
 	mySum:loop
         set total = total + num;
         set num = num - 1;
         # 借助leave组织退出条件
         if num <= 0 then
             leave mySum;
         end if; 
     end loop mySum;
 	SELECT total;
 END
 call calculate10(10);
-- 需求:查询排名前多少位用户的总分数
drop PROCEDURE if EXISTS calculate11;
CREATE PROCEDURE calculate11 (IN num INT(11))
BEGIN
	DECLARE total INT DEFAULT 0;    #总分数
	DECLARE scoreVal INT DEFAULT 0; #每次循环用户分数
	DECLARE offsetVal INT DEFAULT 0;#每次查询SQL的偏移值
	mySum:loop
		SELECT score INTO scoreVal from user order by score DESC limit offsetVal, 1;
    set total = total + scoreVal;   #添加总分数
		set offsetVal = offsetVal + 1;  #对偏移值+1
    set num = num - 1; #将需要查询的用户总数减1
    # 当获取的用户总结束时,借助leave组织退出条件
    if num <= 0 then
       leave mySum;
    end if; 
  end loop mySum;
	SELECT total;
END

call calculate11(2);
游标使用(循环遍历)

游标(英文:Cursor)是一种临时的数据库对象,可以指向存储在数据库表中的数据行指针。
语法结构:

DECLARE cursor_name CURSOR FOR select_statement;  #创建游标
OPEN cursor_name; #条开游标
FETCH cursor_name INTO var_name...; #从游标中获取数据
CLOSE cursor_name; #关闭游符
DEALLOCATE PREPARE cursor_name; #释放游标

使用样例:

#通过游标将所有分组小于60分的用户,添加10分;
drop PROCEDURE if EXISTS updateScore;
CREATE PROCEDURE updateScore()
BEGIN

	DECLARE uid VARCHAR(20);
	DECLARE scoreValue VARCHAR(20);
	DECLARE done INT DEFAULT FALSE;

    # 定义游标
	DECLARE curr CURSOR FOR SELECT id, score FROM user;

	# 声明异常处理
	# 执行到没有查询结果的sql语句,会抛出NOT FOUND,这样游标将不会继续循环;
	DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;

    # 打开游标
	OPEN curr;
	
	# 循环读取
	read_loop : LOOP
		# 获取游标数据
		FETCH NEXT FROM curr INTO uid, scoreValue;
		# 判断游标结束
		IF done THEN
			LEAVE read_loop;
		END IF;

		# 调用更新线上数据脚本
		IF uid is not null AND scoreValue is not null THEN
			update user set score = score+10 where id = uid;
		END IF;
 	END LOOP;
	
	# 关闭游标
	CLOSE curr;

	# 释放游标 v5.7/v8.0报错 Unknown prepared statement handler (curr) given to DEALLOCATE PREPARE 
	#DEALLOCATE PREPARE curr;
END	

call updateScore();

测试表结构如下:

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(64) NOT NULL,
  `password` varchar(64) NOT NULL,
  `city` varchar(128) DEFAULT NULL,
  `area` varchar(128) DEFAULT NULL,
  `score` int(11) DEFAULT NULL,
  `datetime` datetime DEFAULT NULL,
  `unixtime` double DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4;

参考文档:https://blog.csdn.net/qq_32681589/article/details/133376821

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值