MySQL基本操作整理(九)、MySQL中的变量、存储过程、函数与流程控制结构

本文介绍MySQL数据库中的变量、存储过程、函数以及流程控制结构。这一块是MySQL基础中不会频繁涉及的,但一旦使用就会极大提高工作效率的,特别是存储过程函数

一、变量

MySQL中的变量主要分为系统变量自定义变量,系统变量又分为全局变量和会话变量,自定义变量分为用户变量和局部变量。

(一)系统变量

系统变量是由系统定义,不是用户定义的,属于服务器层面的变量。在系统变量中,又分为全局变量和会话变量,全局变量需要添加global关键字,针对于所有会话(连接)有效,但不能跨重启(重启服务器后失效,可通过修改配置文件进行设置);会话变量需要添加session关键字,针对于当前会话(连接)有效;如果不写标识,默认是会话变量。

系统变量的使用

  1. 查看所有系统变量
    show global |【session】variables;
  2. 查看满足条件的部分系统变量
    show global |【session】 variables like ‘%char%’;
  3. 查看指定的系统变量的值
    select @@global. |【session.】系统变量名; (注意是两个@,如查自动提交变量:select @@global.autocommit; )
  4. 为某个系统变量赋值
    方式一:
    set global |【session】系统变量名=值; (如设置自动提交:set session autocommit = 1;)
    方式二:
    set @@global. |【session.】系统变量名=值;(如设置不自动提交:set @@session.autocommit = 0;)

记住上面的使用语法就可以了,下面是对全局变量和会话变量的分别介绍。

1.全局变量

作用域:针对于所有会话(连接)有效,但不能跨重启。
使用

  1. 查看所有全局变量
    SHOW GLOBAL VARIABLES;
  2. 查看满足条件的部分系统变量
    SHOW GLOBAL VARIABLES LIKE ‘%char%’;
  3. 查看指定的系统变量的值
    SELECT @@global.autocommit;
  4. 为某个系统变量赋值
    方式一:
    SET @@global.autocommit=0;
    方式二:
    SET GLOBAL autocommit=0;

2.会话变量

作用域:针对于当前会话(连接)有效。
使用

  1. 查看所有会话变量
    SHOW SESSION VARIABLES;
  2. 查看满足条件的部分会话变量
    SHOW SESSION VARIABLES LIKE ‘%char%’;
  3. 查看指定的会话变量的值
    SELECT @@session.autocommit; (其中session.可省略,即等效于SELECT @@autocommit;)
  4. 为某个会话变量赋值
    方式一:
    SET @@session.autocommit=0;
    方式二:
    SET SESSION autocommit=0;

(二)自定义变量

自定义变量由用户自定义创建,以满足开发过程的使用。

1.用户变量

用户变量针对于当前会话(连接)有效,作用域同于会话变量。使用时和Java中使用变量一样,分三步:声明、赋值、使用(有查看变量值、比较、运算等)
(1)声明(MySQL中的用户变量声明时必须初始化)。写法如下,必须在变量名前加@符号,支持的赋值符号为=和 :=,但若使用select则必须使用 := 的写法(因为分不清是否为比较运算);声明用户变量不用声明类型。
SET @变量名=值;(由于等于号会有歧义,如将它与其他值进行比较,因此有下面 := 的写法)
SET @变量名:=值;
SELECT @变量名:=值;
(2)赋值(或者叫更新变量值)
方式一:
SET @变量名=值;
SET @变量名:=值;
SELECT @变量名:=值;
方式二:
SELECT 字段 INTO @变量名 FROM 表;
(3)查看变量的值
SELECT @变量名;
案例:用户变量的使用

#声明并赋值
SET @name='john';
SET @name=100;#为变量赋值,修改值,同时修改类型
SET @count=1;

#修改变量的值
SELECT COUNT(*) INTO @count FROM myemployees.employees;

#查看变量的值
SELECT @count;

2.局部变量

局部变量仅仅在定义它的begin end块中有效,并且需要在 begin end中的第一句话开始定义。其使用严格遵循三步走。
(1)声明
DECLARE 变量名 类型 【DEFAULT 值】;
(2)赋值
方式一(与用户变量的赋值相同,也是有三种写法,第三种仍然需要加上@符号):
SET 局部变量名=值;
SET 局部变量名:=值;
SELECT @局部变量名:=值;
方式二:
SELECT 字段 INTO 局部变量名 FROM 表;
(3)查看变量的值
SELECT 局部变量名;
案例1:局部变量的申明与使用

扫描二维码关注公众号,回复: 11362756 查看本文章
#下面的语句单独执行没有用哦,需要放在begin end中,如案例2的存储过程
DECLARE m INT DEFAULT 1;
DECLARE n INT DEFAULT 1;
DECLARE SUM INT;
SET SUM=m+n;
SELECT SUM;

案例2:向account表中插入姓名为“Tom”,年龄为用户m(10岁) 和用户n(15岁)之和的一条记录。(涉及到下面的存储过程)

DELIMITER $ #修改sql语句结束的标记为$
CREATE PROCEDURE p1(IN username VARCHAR(20))
BEGIN
	DECLARE m INT DEFAULT 10;
	DECLARE n INT DEFAULT 15;
	DECLARE SUM INT;
	SET SUM = m + n;
	INSERT INTO account (account.username, age) VALUES (username, SUM);
END $

用户变量和局部变量的对比:

变量类型 作用域 定义位置 语法
用户变量 当前会话 会话的任何地方 加@符号,不用指定类型
局部变量 定义它的BEGIN END中 BEGIN END的第一句话 一般不用加@,需要指定类型

二、存储过程

MySQL中的存储过程和函数是相对比较高级的特征,一般的大型的数据库管理系统都具有这样的特征,类似于java中的方法,下面先介绍存储过程。

1.存储过程介绍

含义:存储过程是一组预先编译好的SQL语句的集合,理解成批处理语句。
使用存储过程的好处

  1. 提高代码的重用性
  2. 简化操作
  3. 减少了编译次数并且减少了和数据库服务器的连接次数,提高了效率

创建语法:

DELIMITER 结束标记 #存储过程结尾的符号设置
CREATE PROCEDURE 存储过程名(参数列表)
BEGIN
	存储过程体(一组合法的SQL语句)
END 结束标记

注意:
1、参数列表包含三部分:(参数模式 参数名 参数类型)
如:CREATE PROCEDURE myp1 (IN stuname VARCHAR(20)) …
参数模式:
in:该参数可以作为输入,也就是该参数需要调用方传入值
out:该参数可以作为输出,也就是该参数可以作为返回值
inout:该参数既可以作为输入又可以作为输出,也就是该参数既可以传入值,又可以返回值

2、如果存储过程体仅仅只有一句话,begin end可以省略
3、存储过程体中的每条sql语句的结尾要求必须加分号。
存储过程的结尾可以使用 delimiter 重新设置,语法为:
delimiter 结束标记,如:delimiter $

调用语法:
CALL 存储过程名(实参列表);

2.存储过程创建案例

案例1(空参列表的存储过程):创建一个存储过程,实现插入到admin表中五条记录。

#创建
DELIMITER $
CREATE PROCEDURE myp1()
BEGIN
	INSERT INTO admin(username,`password`) 
	VALUES('john1','0000'),('lily','0000'),('rose','0000'),('jack','0000'),('tom','0000');
END $

#调用
CALL myp1()$
#查看
select * from admin$

案例2(创建带in模式参数的存储过程):创建存储过程实现,根据女神名查询对应的男神信息。

#创建
CREATE PROCEDURE myp2(IN beautyName VARCHAR(20))
BEGIN
	SELECT bo.*
	FROM boys bo
	RIGHT JOIN beauty b ON bo.id = b.boyfriend_id
	WHERE b.name = beautyName;
END $

#调用
CALL myp2('柳岩')$

案例3(创建带两个in模式参数的存储过程):创建存储过程实现,判断用户是否登录成功,即用户名和密码是否匹配。

#创建
CREATE PROCEDURE myp3(IN username VARCHAR(20),IN PASSWORD VARCHAR(20))
BEGIN
	DECLARE result INT DEFAULT 0;#声明并初始化	
	SELECT COUNT(*) INTO result#赋值
	FROM admin
	WHERE admin.username = username
	AND admin.password = PASSWORD;	
	SELECT IF(result>0,'成功','失败') 状态;#使用
END $

#调用
CALL myp3('张飞','8888')$

案例4(创建带out模式参数的存储过程):根据输入的女神名,返回对应的男神名和魅力值

#创建
CREATE PROCEDURE myp4(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20),OUT usercp INT) 
BEGIN
	SELECT boys.boyname ,boys.usercp INTO boyname,usercp
	FROM boys 
	RIGHT JOIN
	beauty b ON b.boyfriend_id = boys.id
	WHERE b.name=beautyName ;	
END $

#调用
CALL myp4('小昭',@name,@cp)$
SELECT @name,@cp$

案例5(创建带inout模式参数的存储过程):传入a和b两个值,最终a和b都翻倍并返回

CREATE PROCEDURE myp5(INOUT a INT ,INOUT b INT)
BEGIN
	SET a=a*2;
	SET b=b*2;
END $

#调用
SET @m=10$ #需要先定义变量
SET @n=20$
CALL myp5(@m,@n)$
SELECT @m,@n$

3.删除存储过程

语法:drop procedure 存储过程名
存储过程只能一次删除一个,不支持同时删除多个存储过程。
DROP PROCEDURE p1;
DROP PROCEDURE p2,p3;#错误,不支持

4.查看存储过程信息

语法:SHOW CREATE PROCEDURE myp1;
不能使用 DESC myp1;的方式

三、函数

1.函数介绍

含义:函数和存储过程一样,是一组预先编译好的SQL语句的集合,当然就具有以下的特点:
1、提高代码的重用性
2、简化操作
3、减少了编译次数并且减少了和数据库服务器的连接次数,提高了效率

函数和存储过程的区别
存储过程:可以有0个返回,也可以有多个返回,适合做批量插入、批量更新
函数:有且仅有1 个返回,适合做处理数据后返回一个结果

创建语法

#创建函数的语法注意写的是RETURNS,具体使用查看下面案例
CREATE FUNCTION 函数名(参数列表) RETURNS 返回类型
BEGIN
	函数体
END

注意
1、参数列表包含两部分:参数名 参数类型
2、函数体:肯定会有return语句,如果没有会报错
如果return语句没有放在函数体的最后不报错,但不建议
3、函数体中仅有一句话,则可以省略begin end
4、使用 delimiter语句设置结束标记

调用语法
SELECT 函数名(参数列表)

2.函数创建案例

案例1(无参有返回):返回公司的员工个数

#创建
CREATE FUNCTION myf1() RETURNS INT
BEGIN
	DECLARE c INT DEFAULT 0;#定义局部变量
	SELECT COUNT(*) INTO c#赋值
	FROM employees;
	RETURN c;	
END $
#调用
SELECT myf1()$

案例2(有参有返回):根据员工名,返回它的工资

#创建
CREATE FUNCTION myf2(empName VARCHAR(20)) RETURNS DOUBLE
BEGIN
	SET @sal=0;#用户变量的作用域为当前会话,放在哪里都行 
	SELECT salary INTO @sal #赋值
	FROM employees
	WHERE last_name = empName;	
	RETURN @sal;
END $
#调用
SELECT myf2('k_ing') $

案例3(有参有返回):根据部门名,返回该部门的平均工资

#创建
CREATE FUNCTION myf3(deptName VARCHAR(20)) RETURNS DOUBLE
BEGIN
	DECLARE sal DOUBLE ;
	SELECT AVG(salary) INTO sal
	FROM employees e
	JOIN departments d ON e.department_id = d.department_id
	WHERE d.department_name = deptName;
	RETURN sal;
END $
#调用
SELECT myf3('IT')$

3.查看函数

语法:SHOW CREATE FUNCTION myf3;
MySQL数据库中的所有存储过程和函数,存在mysql这个数据库的 proc表中,并且用类型PROCEDURE和FUNCTION加以区别。

4.删除函数

语法:DROP FUNCTION myf3;

四、流程控制结构

mysql中的流程控制结构包括:顺序结构、分支结构与循环结构。

顺序结构:程序从上往下依次执行
分支结构:程序从两条或多条路径中选择一条去执行
循环结构:程序在满足一定条件的基础上,重复执行一段代码

顺序结构很好理解,程序从上往下执行即可,下面主要介绍分支结构和循环结构。

(一)分支结构

1.if函数

功能:实现简单的双分支,类似于java中的if else
语法:if(表达式1, 表达式2, 表达式3)
执行顺序
如果表达式1成立,则if函数返回表达式2的值,否则返回表达式3的值
应用范围:可以应用在任何地方(如存储过程和函数中,begin end中或外面)

2.case结构

(1)case作为表达式,可以放在begin end中或者begin end外,语法:

情况一:
case 变量|表达式|字段
when 要判断的值 then 返回的值1
when 要判断的值 then 返回的值2

else 返回的值n
end
 
情况二:
case
when 要判断的条件1 then 返回的值1
when 要判断的条件2 then 返回的值2

else 返回的值n
end

(2)case作为独立语句,只能放在begin end中,语法:

情况一:
case 变量|表达式|字段
when 要判断的值 then 语句1;
when 要判断的值 then 语句2;

else 语句n;
end case;
 
情况二:
case
when 要判断的条件1 then 语句1;
when 要判断的条件2 then 语句2;

else 语句n
end case;

特点:
1.可以作为表达式,嵌套在其他语句中使用,可以放在任何地方,begin end 中或begin end的外面;可以作为独立的语句去使用,只能放在begin end中
2.如果when中的值满足或条件成立,则执行对于功能的then后面的语句,并且结束case
如果都不满足,则执行else中的语句或值
3.else可以省略,如果else省略了,并且所有when条件都不满足,则返回null

案例(case作为独立语句的情况):创建存储过程,根据传入的成绩,来显示等级,如果成绩为90-100,显示A,80-90,显示B,60-80,显示C,否则,显示D

CREATE PROCEDURE test_case (IN score INT)
BEGIN
	CASE
	WHEN score>=90 AND score<=100 THEN SELECT 'A';
	WHEN score>=80 THEN SELECT 'B';
	WHEN score>=60 THEN SELECT 'C';
	ELSE SELECT 'D';
	END CASE; 
END $

3.if结构

功能:实现多重分支
语法

if 条件1 then 语句1;
elseif 条件2 then 语句2; #注意elseif中间没有空格

【else 语句n;】
end if;

应用范围:只能应用在begin end 中

案例(使用if结构):创建函数,实现传入成绩,如果成绩>90,返回A,如果成绩>80,返回B,如果成绩>60,返回C,否则返回D

CREATE FUNCTION test_if(score INT) RETURNS CHAR
BEGIN
	IF score>=90 AND socre<=100 THEN RETURN 'A';
	ELSEIF score>=80 THEN RETURN 'B';
	ELSEIF score>=60 THEN RETURN 'C';
	ELSE RETURN 'D';
	END IF;		
END $

#当然也可以用case的写法:
CREATE FUNCTION f1(score INT) RETURNS CHAR
BEGIN
	DECLARE a CHAR;
	CASE
	WHEN score>=90 AND score<=100 THEN SET a = 'A';
	WHEN score>=80 THEN SET a = 'B';
	WHEN score>=60 THEN SET a = 'C';
	ELSE SET a = 'D';
	END CASE;
	RETURN a;
END $

(二)循环结构

介绍:
MySQL中的循环结构分三类:while、loop、repeat

循环控制(即跳转语句):
iterate 类似于 continue,继续,结束本次循环,继续下一次
leave 类似于 break,跳出,结束当前所在的循环

语法:
while:(重点)

【标签:】while 循环条件 do
循环体;
end while【 标签】;

loop:(可以用来模拟简单的死循环)

【标签:】loop
循环体;
end loop 【标签】;

repeat:(类似于do while)

【标签】repeat
循环体;
until 结束循环的条件
end repeat 【标签】;

案例1(while案例):批量插入,根据次数插入到admin表中多条记录

CREATE PROCEDURE pro_while1(IN insertCount INT)
BEGIN
	DECLARE i INT DEFAULT 1;
	WHILE i<=insertCount DO
		INSERT INTO admin(username,`password`) VALUES(CONCAT('Rose',i),'666');#password是关键字,可以加着重号来区别
		SET i=i+1;
	END WHILE;	
END $

案例2(添加leave语句):批量插入,根据次数插入到admin表中多条记录,如果次数>20则停止

CREATE PROCEDURE test_while1(IN insertCount INT)
BEGIN
	DECLARE i INT DEFAULT 1;
	a:WHILE i<=insertCount DO
		INSERT INTO admin(username,`password`) VALUES(CONCAT('xiaohua',i),'0000');
		IF i>=20 THEN LEAVE a;
		END IF;
		SET i=i+1;
	END WHILE a;
END $

案例3(添加iterate语句):批量插入,根据次数插入到admin表中多条记录,只插入偶数次

CREATE PROCEDURE test_while1(IN insertCount INT)
BEGIN
	DECLARE i INT DEFAULT 0;
	a:WHILE i<=insertCount DO
		SET i=i+1;
		IF MOD(i,2)!=0 THEN ITERATE a;
		END IF;		
		INSERT INTO admin(username,`password`) VALUES(CONCAT('xiaohua',i),'0000');		
	END WHILE a;
END $

案例4(流程控制经典案例):创建存储过程,向 stringcontent 表中插入指定个数的随机字符串(长度也随机),该表的结构如下:
CREATE TABLE stringcontent (
id INT PRIMARY KEY AUTO_INCREMENT,
content VARCHAR(20)
);

CREATE PROCEDURE test_randstr_insert(IN insertCount INT)
BEGIN
	DECLARE i INT DEFAULT 1;
	DECLARE str VARCHAR(26) DEFAULT 'abcdefghijklmnopqrstuvwxyz';#随机字符串从str字符串中取子串
	DECLARE startIndex INT DEFAULT 1;
	DECLARE len INT DEFAULT 1;
	WHILE i<=insertCount DO
		SET len = FLOOR(RAND()*(20-startIndex+1) + 1);#产生一个随机的整数,代表截取长度,1-(26-startIndex+1),此处定义的字符串最大长度为20
		SET startIndex=FLOOR(RAND()*26+1);#产生一个随机整数,代表起始索引1-26,RAND()为0~1,RAND()*26为0.X~25.x,加一再向下取整得到1~26
		INSERT INTO stringcontent(content) VALUES(SUBSTR(str,startIndex,len));
		SET i = i+1;#循环变量更新
	END WHILE;
END $

猜你喜欢

转载自blog.csdn.net/shao_yc/article/details/106221108