一、数据库的变量
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。