MySQL(六)—— 数据库编程:控制语句、数据库函数、存储过程、触发器等

一、数据库的变量

1、系统变量
(1)系统变量顾名思义就是系统提供的变量,属于服务器层面上的,存放在数据库服务端,用于设置整个数据库的变量,如autocommit。
如果是全局级别,则需要添加GLOBAL,如果是会话级别,则添加SESSION,如果不写则默认SESSION。
作用域:服务器每次启动将为所有的全局变量赋初始值,针对于所有的会话(连接)有效,但不能跨重启(即修改过的系统变量在重启会恢复默认值)。
(2)语法:
① 查看所有的系统变量

SHOW GLOBAL VARIABLES; -- 全局系统变量

② 查看满足条件的部分系统变量

SHOW GLOBAL VARIABLES like '%char%';

③ 查看指定的某个系统变量的值

SELECT @@系统变量名;
SELECT @@GLOBAL.系统变量名;
-- eg:
SELECT @@GLOBAL.autocommit;

④ 设置系统变量名(修改系统变量)
系统变量会控制所有的用户,一旦修改了系统变量,那么所有的连接都将修改。
第一种方式:直接修改 这种修改方式只能修改当前连接客户端的系统变量

SET 系统变量名 := 值;

第二种方式:这种修改能够作用到整个数据库服务端的系统变量,但使用这种方式修改, 当前连接的客户端不会起作用,只有重新连接的客户端才会起作用。

SET @@GLOBAL.系统变量 = 值;
--eg:
SET @@GLOBAL.autocommit = 0;

2、会话变量
(1)当前连接的会话起作用。
作用域:仅仅针对于当前会话(连接)有效。
(2)语法
① 查看所有会话变量

SHOW  VARIABLES;
SHOW SESSION VARIABLES;

② 查看部分会话变量

SHOW  VARIABLES LIKE '%char%';
SHOW SESSION VARIABLES LIKE '%char%';

③ 查看指定的某个会话变量

SET @@会话变量名;
SET @@SESSION.会话变量;

④ 为某个会话变量赋值(修改会话变量值)

SET @@会话变量 = 值;
SET @@SESSION.会话变量 = 值;
SET SESSION 会话变量名 = 值;

3、局部变量
(1)只能作用域区域的变量,作用域是begin和end区域之间,并且使用declare关键字进行定义
(2)步骤
① 声明

DECLARE 变量名 类型;
DECLARE 变量名 类型; DEFAULT 值;
DECLARE i INT DEFAULT 0 ;

② 赋值(修改)
方式一

SET @局部变量名 = 值;
SET @局部变量名 := 值;
SELECT @局部变量名 := 值;

方式二

SELECT 字段 INTO @局部变量名 FROM 表;

③ 使用(查看)

SELECT @局部变量名;

4、自定义变量
(1)用户自己定义的变量,不是系统的,针对于当前会话有效,等同于会话变量的作用域,但是可以应用在任何位置,begin和end里面可以,外面也可以
(2)使用步骤
① 声明并初始化

SET @用户变量名 = 值;
SET @用户变量名 := 值;
SELECT @用户变量名 := 值;

因为 " =" 容易有歧义,所以MySQL又推荐另一种写法,":=" 。

② 赋值(修改用户变量的值)
第一种:

SET @用户变量名 = 值;
SET @用户变量名 := 值;
SELECT @用户变量名 := 值;

第二种:

SELECT 字段 INTO @用户变量名 FROM 表;

③ 使用(查看用户变量的值)

SELECT @用户变量名;

二、控制语句——分支、循环

1、IF分支
语法:

IF 条件1 THEN
	执行语句1;
ELSE IF 条件2  THEN
	执行语句2;
...
ELSE
	执行语句n;
END IF;

Demo:根据传入的分数判断成绩等级

-- 根据传入的分数判断成绩等级
delimiter &&
CREATE FUNCTION method5(score INT) RETURNS CHAR
BEGIN
	IF score >= 90 AND score <= 100 THEN
		RETURN 'A';
	ELSEIF score >= 80 THEN
		RETURN 'B';
	ELSEIF score >= 60 THEN
		RETURN 'C';
	ELSE
		RETURN 'D';
	END IF;
END
&&
delimiter ;
SELECT method5(85);

2、CASE分支
(1)类似于java中的switch,一般用于实现等值判断。
语法:

CASE 变量|表达式|字段
WHEN 值1 THEN 返回的值1或执行语句1;
WHEN 值2 THEN 返回的值2执行语句2;
...
ELSE 执行语句n;
END CASE;

是返回值的话不用加分号。

CASE 变量|表达式|字段
WHEN 值1 THEN 返回的值1
WHEN 值2 THEN 返回的值2
...
ELSE 执行语句n
END

(2)类似于java中的多重if语句,一般用于实现区间判断。
语法:

CASE
WHEN 条件1 THEN 返回的值1执行语句1;
WHEN 条件2 THEN 返回的值2执行语句2;
...
ELSE 执行语句n;
END CASE;

注意:
(1)可以作为表达式,嵌套在其他语句中,可以放在任何位置,BEGIN和END里面和外面。可以作为独立的语句,只能放置BEGIN和END里面使用。
如上述语法中,如果是执行语句,满足条件并执行对应语句之后就跳出整个结构,不满足条件则继续往下执行。
(2)如果WHEN中的值满足或条件成立,则执行对应的THEN后面的语句,并且结束CASE,如果都不满足,则执行ELSE中的语句。
(3)ELSE可以省略,如果省略了,并且所有的WHEN的条件都不满足,则返回NULL。
Demo:根据传入的分数判断成绩等级

-- 根据传入的分数判断成绩等级
delimiter &&
CREATE PROCEDURE method4(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
&&
delimiter ;
CALL method4(85);

3、WHILE循环
(1)分类
WHILE、LOOP、REPEAT
(2)循环控制
① leave: 离开循环,相当于java中的break,结束整个循环
② iterate:持续迭代,相当于java中的continue,结束本次循环继续下次循环
(3)语法:
① WHILE的语法

[标记:] WHILE 条件判断 DO
	循环语句;
END WHILE [标记];

Demo:存储过程实现100-500之间的累加

-- 存储过程实现100-500之间的累加
delimiter &&
CREATE PROCEDURE method2()
BEGIN
	DECLARE sum INT DEFAULT 0;
	DECLARE i INT DEFAULT 100;
	WHILE i <= 500 DO
		SET sum := sum + i;
		SET i := i + 1;
	END WHILE;
	SELECT sum;
END
&&
delimiter ;
-- 查询存储过程
SHOW PROCEDURE STATUS;
-- 调用函数查看结果
CALL method2();

② LOOP的语法

[标记:] LOOP
	循环语句;
END LOOP [标记];

可以用来模拟简单的死循环

③ REPEAT的语法

[标记:] REPEAT
	循环语句;
UNTIL 结束循环的条件
END REPEAT [标记];

Demo1:计算100以内的偶数和

-- 计算100以内的偶数和
-- 方法一
delimiter &&
CREATE FUNCTION method() RETURNS INT
BEGIN
	DECLARE sum INT DEFAULT 0;
	DECLARE i INT DEFAULT 0;
	-- WHILE 循环进行循环
	p1:WHILE i <= 100 DO
		-- IF 分支进行判断
		IF i % 2 = 0 THEN
			SET sum := sum + i;
		END IF;
		SET i := i + 1;
	END WHILE p1;
	RETURN sum;
END;
&&
delimiter ;
-- 调用函数查看结果
SELECT method();

-- 方法二
delimiter &&
CREATE FUNCTION method1() RETURNS INT
BEGIN
	DECLARE i INT DEFAULT 0;
	DECLARE sum INT DEFAULT 0;
	p1:WHILE i < 100 DO
		SET sum := sum + i;
		if i % 2 <> 0 THEN
			-- 重新从p1出开始迭代
			ITERATE p1;
		END IF;
		SET sum := sum + i;
	END WHILE p1;
	RETURN sum;
END
&&
delimiter ;
-- 调用函数查看结果
SELECT method1();

Demo2:计算x的y次方

-- 计算x的y次方
delimiter &&
CREATE PROCEDURE method3()
BEGIN
	DECLARE x INT DEFAULT 2;
	DECLARE y INT DEFAULT 4;
	DECLARE i INT DEFAULT 0;
	DECLARE res DOUBLE DEFAULT 1.0;
	IF y > 0 THEN
		p1:WHILE i < y DO
			SET res = res * x;
			SET i = i + 1;
		END WHILE p1;
	END IF;

	IF y < 0 then
		set y = y * (-1);
		p2:WHILE i < y DO
			SET res = res * x;
			SET i = i + 1;
		END WHILE p2;
		set res = 1 / res;
		SELECT sum;
	END IF;

	IF y = 0 THEN
		SET res = 1;
	END IF;
	SELECT res;
END;
&&
delimiter ;
-- 调用函数查看结果
CALL method3();

三、函数

1、基本函数
① 获取字符的长度

char_length();

② 获取字符串的字节数

length();

③ 截取函数:

left("你好世界",1); -- 从左边开始截取多少个 
right();从右边截取,同上 
mid();从中间截取

④ 时间函数

curdate(); -- 获取当前日期:年月日 
curtime(); -- 获取当前时间
now(); -- 获取当前的日期 + 时间

⑤ 去空格

ltrim(); -- 去掉前面空格 
rtrim(); -- 去掉后面空格 
trim(); -- 去掉前后空格

⑥ 数学函数

pow(); -- 指数运算,如select POW(2,3); 
random(); -- 产生0-1的随机小数

2、自定义函数
(1)实现一个特定功能的代码块
(2)语法
① 创建函数

CREATE FUNCTION 函数名([参数名 数据类型]) RETURNS 返回值数据类型 
BEGIN
	函数的功能语句
	RETURN 返回值
END;

注意:
1> 函数体肯定会有返回值,但没有也不会报错,如果RETURN语句没有放在函数体的最后,也不会报错,但是不建议这么放置;
2> 如果函数体中只有一句话,可以省略BEGIN和END;
3> delimiter 语句设置结束标记。

② 查询函数

-- 查询函数
SHOW FUNCTION  STATUS;
SHOW CREATE FUNCTION 函数名; -- 函数名后不加括号

③ 调用函数

	SELECT 函数名(参数列表);

④ 删除函数

DROP FUNCTION  函数名; -- 函数名后不加括号

Demo1:通过函数简单计算

-- 计算1 + 2 方式1
delimiter &&
CREATE FUNCTION method() RETURNS INT
BEGIN
	DECLARE sum INT DEFAULT 0;
	DECLARE i INT DEFAULT 1;
	DECLARE j INT DEFAULT 2;
	SET sum := i + j;
	RETURN sum;
END;
&&
delimiter ;
-- 调用函数查看结果
SELECT method();

-- 计算1 + 2 方式2
delimiter &&
CREATE FUNCTION method(i INT,j INT) RETURNS INT
BEGIN
	DECLARE sum INT DEFAULT 0;
	SET sum := i + j;
	RETURN sum;
END;
&&
delimiter ;
-- 调用函数查看结果
SELECT method(1,2);

四、存储过程 procedure

1、类似函数,为了实现特定功能的代码,但是没有返回值。

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

3、创建存储过程

CREATE PROCEDURE 存储过程名(参数模式 参数名 参数类型)
BEGIN
	存储过程体(一组合法的SQL语句);
END

注意:
(1)参数模式:
IN:表示该参数只能从存储过程的外面传到存储过程的里面使用;
OUT:表示该参数只能从存储过程的黎明传到存储过程的外面使用;
INOUT:既可以从存储过程的外面传入到里面使用,也可以从里面传入到外面使用。
(2)如果存储过程体仅仅只有一句话,BEGIN和END可以省略。
(3)存储过程体重的每条SQL语句的结尾必须要加分号";"。
(4)存储过程的结尾可以使用 DELIMITER 重新设置
语法:

delimiter 结束标记
如
delimiter &&

4、查询存储过程

查询存储过程 
SHOW PROCEDURE STATUS;
查看存储过程信息
SHOW CREATE PROCDURE 存储过程名;

5、删除存储过程

DROP PROCEDURE 存储过程名称;

6、调用存储过程

CALL 存储过程名(实参列表);

Demo1:存储过程实现1 + 2的计算

-- 存储过程实现1 + 2的计算
delimiter &&
CREATE PROCEDURE demo1()
BEGIN
	DECLARE i INT DEFAULT 1;
	DECLARE j INT DEFAULT 2;
	DECLARE sum INT DEFAULT 0;
	SET sum := i + j;
	SELECT sum;
END
&&
delimiter ;
-- 调用函数查看结果
CALL demo1();

Demo2:存储过程实现100-500之间的累加

-- 存储过程实现100-500之间的累加
delimiter &&
CREATE PROCEDURE demo2()
BEGIN
	DECLARE sum INT DEFAULT 0;
	DECLARE i INT DEFAULT 100;
	WHILE i <= 500 DO
		SET sum := sum + i;
		SET i := i + 1;
	END WHILE;
	SELECT sum;
END
&&
delimiter ;
-- 调用函数查看结果
CALL demo2();

Demo3:使用存储过程向数据库表中插入数据

-- 使用存储过程向数据库表中插入数据
delimiter &&
CREATE PROCEDURE demo3()
BEGIN
	DECLARE i int DEFAULT 7;
	p1:WHILE i <= 100 DO
		INSERT INTO student1 VALUES(i,'张三',"s007","id7");
		SET i = i + 1;
	END WHILE p1;
SELECT * FROM student1;
END;
&&
delimiter ;
CALL demo3();

Demo4:IN、OUT、INOUT的分析
在这里插入图片描述

Demo5:创建存储过程实现传入一个日期,格式化成yyyy年mm月dd日并返回

-- 创建存储过程实现传入一个日期,格式化成yyyy年mm月dd日并返回
delimiter &&
CREATE PROCEDURE datedemo(IN mydate DATETIME,OUT strDate VARCHAR(50))
BEGIN
	SELECT DATE_FORMAT(mydate,'%y年%m月%d日') INTO strDate;
END;
&&
delimiter ;
CALL datedemo(NOW(),@str);
SELECT @str;

五、触发器 trigger

1、触发器不用主动调用,一旦满足一定条件,会自动触发。

2、语法
(1)创建触发器

create trigger 触发器名称 触发时机 触发事件 on 表名 for each row
begin
	触发器的代码;
end

Demo:创建一个触发器

-- 创建一个触发器
CREATE TRIGGER tr AFTER INSERT ON orders FOR EACH ROW
BEGIN
	UPDATE product SET pnum = pnum - new.onum WHERE pid = new.pid;
END

(2)查询触发器

SHOW TRIGGERS;

(3)删除触发器

DROP TRIGGER 触发器名字;

3、注意
(1)触发器时机:after,before
(2)触发器事件:insert,delete,update
(3)new:如果是新增语句,使用new。
(4)old:如果是修改和删除,使用old。

猜你喜欢

转载自blog.csdn.net/weixin_43592512/article/details/89644571