查看系统变量:
SHOW [ SESSION | GLOBAL ] VARIABLES ; -- 查看所有系统变量
SHOW [ SESSION | GLOBAL ] VARIABLES LIKE '......'; -- 可以通过LIKE模糊匹配方式查找变量
SELECT @@[SESSION | GLOBAL] 系统变量名; -- 查看指定变量的值
设置系统变量 :
SET [ SESSION | GLOBAL ] 系统变量名 = 值 ;
SET @@[SESSION | GLOBAL]系统变量名 = 值 ;
注意事项:
- 如果没有指定SESSION/GLOBAL,默认是SESSION,会话变量。
- 全局变量(GLOBAL): 全局变量针对于所有的会话。
- 会话变量(SESSION): 会话变量针对于单个会话,在另外一个会话窗口就不生效了。
用户定义变量 是用户根据需要自己定义的变量,用户变量不用提前声明,在用的时候直接用 “@变量名” 使用就可以。其作用域为当前连接。
为自定义变量赋值:
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 ;
局部变量是根据需要定义的在局部生效的变量,访问之前,需要DECLARE
声明。可用作存储过程内的局部变量和输入参数,局部变量的范围是在其内声明的BEGIN … END块。
声明局部变量:
DECLARE 变量名 变量类型 [DEFAULT ... ] ;
赋值:
SET 变量名 = 值 ;
SET 变量名 := 值 ;
SELECT 字段名 INTO 变量名 FROM 表名 ... ;
可以使用 CREATE PROCEDURE 语句创建存储过程,语法格式如下:
CREATE PROCEDURE <过程名> ( [过程参数[,…] ] ) <过程体>
[过程参数[,…] ] 格式
[ IN | OUT | INOUT ] <参数名> <类型>
create procedure p1()
begin
select count(*) from student;
end;
过程名
db_name.sp_name
。需要注意的是,名称应当尽量避免选取与 MySQL 内置函数相同的名称,否则会发生错误。过程参数
IN
、 OUT
和 INOUT
三个关键字标识。其中,输入参数可以传递给一个存储过程,输出参数用于存储过程需要返回一个操作结果的情形,而输入/输出参数既可以充当输入参数也可以充当输出参数。过程体
存储过程的主体部分,也称为存储过程体,包含在过程调用的时候必须执行的 SQL 语句。这个部分以关键字 BEGIN
开始,以关键字 END
结束。若存储过程体中只有一条 SQL 语句,则可以省略 BEGIN-END 标志。
在 MySQL 中,服务器处理 SQL 语句默认是以分号作为语句结束标志的,在命令行中,执行创建存储过程的SQL时,需要通过关键字 DELIMITET
指定SQL语句的结束符。
DELIMITER $$
查看存储过程的状态:
SHOW PROCEDURE STATUS LIKE 存储过程名;
查看存储过程的定义:
SHOW CREATE PROCEDURE 存储过程名;
查询指定数据库的存储过程及状态信息 :
SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = '数据库名';
MySQL 中修改存储过程的语法格式如下:
ALTER PROCEDURE 存储过程名 [ 特征 ... ]
特征指定了存储过程的特性,可能的取值有:
ALTER PROCEDURE 语句用于修改存储过程的某些特征。如果要修改存储过程的内容,可以先删除原存储过程,再以相同的命名创建新的存储过程 。
MySQL 中使用 DROP PROCEDURE 语句来删除数据库中已经存在的存储过程。语法格式如下:
DROP PROCEDURE [ IF EXISTS ] <过程名>
MySQL 中使用 CALL
语句来调用存储过程。调用存储过程后,数据库系统将执行存储过程中的 SQL 语句并将结果返回给输出值。
CALL procedure_name([parameter[...]]);
存储过程的参数的类型,主要分为以下三种:IN、OUT、INOUT。 具体的含义如下:
类型 | 含义 | 备注 |
---|---|---|
IN | 该类参数作为输入,也就是需要调用时传入值 | 默认 |
OUT | 该类参数作为输出,也就是该参数可以作为返回值 | |
INOUT | 既可以作为输入参数,也可以作为输出参数 |
案例1:根据传入参数score,判定当前分数对应的分数等级,并返回。score >= 85分,等级为优秀。score >= 60分 且 score < 85分,等级为及格。score < 60分,等级为不及格。
CREATE PROCEDURE p2(in score int ,out result varchar(10))
BEGIN
IF score >= 85 THEN
SET result = '优秀';
ELSEIF score >= 60 THEN
SET result = '中等';
ELSE
SET result = '不及格';
end IF;
END
call p2(90,@result);
SELECT @result;
案例2:将传入的200分制的分数,进行换算,换算成百分制,然后返回。
create procedure p5(inout score double)
begin
set score := score * 0.5;
end;
set @score = 198;
call p5(@score);
select @score;
IF 语句
、 CASE 语句
、 LOOP 语句
、 LEAVE 语句
、 ITERATE 语句
、 REPEAT
语句和 WHILE
语句等。IF 语句用来进行条件判断,根据是否满足条件(可包含多个条件),来执行不同的语句,是流程控制中最常用的判断语句。其语法的基本形式如下:
IF search_condition THEN statement_list
[ELSEIF search_condition THEN statement_list]...
[ELSE statement_list]
END IF
案例:根据定义的分数score变量,判定当前分数对应的分数等级。score >= 85分,等级为优秀。score >= 60分 且 score < 85分,等级为及格。score < 60分,等级为不及格。
create procedure p3()
begin
declare score int default 58;
declare result varchar(10);
if score >= 85 then
set result := '优秀';
elseif score >= 60 then
set result := '及格';
else
set result := '不及格';
end if;
select result;
end;
call p3();
CASE 语句也是用来进行条件判断的,它提供了多个条件进行选择,可以实现比 IF 语句更复杂的条件判断。 CASE 语句的基本形式如下:
CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list]...
[ELSE statement_list]
END CASE
案例:根据传入的月份,判定月份所属的季节(要求采用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(16);
WHILE 语句也是有条件控制的循环语句。 WHILE 语句和 REPEAT 语句不同的是, WHILE 语句是当满足条件时,执行循环内的语句,否则退出循环。 WHILE 语句的基本语法形式如下:
[begin_label:] WHILE search_condition DO
statement list
END WHILE [end label]
案例:计算从1累加到n的值,n为传入的参数值。
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);
REPEAT 语句是有条件控制的循环语句,每次语句执行完毕后,会对条件表达式进行判断,如果表达式返回值为 TRUE,则循环结束,否则重复执行循环中的语句。REPEAT 语句的基本语法形式如下:
[begin_label:] REPEAT
statement_list
UNTIL search_condition
END REPEAT [end_label]
案例:计算从1累加到n的值,n为传入的参数值。(使用repeat实现) 。
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(10);
LOOP 实现简单的循环,如果不在SQL逻辑中增加退出循环的条件,可以用其来实现简单的死循环。
[begin_label:] LOOP
SQL逻辑...
END LOOP [end_label];
LOOP可以配合一下两个语句使用:
案例:计算从1到n之间的偶数累加的值,n为传入的参数值。
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);
声明
、OPEN
、FETCH
和 CLOSE
,其语法分别如下。声明游标:
DECLARE 游标名称 CURSOR FOR 查询语句 ;
打开游标:
OPEN 游标名称 ;
获取游标记录:
FETCH 游标名称 INTO 变量 [, 变量 ] ;
关闭游标:
CLOSE 游标名称 ;
案例:根据传入的参数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 upro 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,upro;
insert into tb_user_pro values (null, uname, upro);
end while;
close u_cursor;
end;
call p11(30);
上述代码中循环的控制还需使用定义条件和处理程序进一步优化。
MySQL 中可以使用 DECLARE 关键字来定义条件。其基本语法如下:
DECLARE condition_name CONDITION FOR condition_value
condition value:
SQLSTATE [VALUE] sqlstate_value | mysql_error_code
condition_name 参数表示条件的名称;
condition_value 参数表示条件的类型;
sqlstate_value 参数和 mysql_error_code 参数都可以表示 MySQL 的错误。 sqlstate_value 表示长度为 5 的字符串 类型错误代码, mysql_error_code 表示数值类型错误代码。例如 ERROR 1146(42S02) 中, sqlstate_value 值是42S02,mysql_error_code 值是 1146。
案例:下面定义“ERROR 1146 (42S02)”这个错误,名称为 can_not_find。 可以用两种不同的方法来定义,代码如下:
//方法一:使用 sqlstate_value
DECLARE can_not_find CONDITION FOR SQLSTATE '42S02';
//方法二:使用 mysql_error_code
DECLARE can_not_find CONDITION FOR 1146;
MySQL 中可以使用 DECLARE 关键字来定义处理程序。其基本语法如下:
DECLARE handler_type HANDLER FOR condition_value[...] sql_statement
handler_type:
CONTINUE | EXIT | UNDO
condition_value:
SQLSTATE [VALUE] sqlstate_value | condition_name | SQLWARNING | NOT FOUND | SQLEXCEPTION |
mysql_error_code
其中, handler_type
参数指明错误的处理方式,该参数有 3 个取值。这 3 个取值分别是 CONTINUE
、 EXIT
和UNDO
。
CONTINUE 表示遇到错误不进行处理,继续向下执行;
EXIT 表示遇到错误后马上退出;
UNDO 表示遇到错误后撤回之前的操作, MySQL 中暂时还不支持这种处理方式。
参数指明错误类型,该参数有 6 个取值:
更多操作sqlstate_value:包含 5 个字符的字符串错误值;
condition_name:表示 DECLARE 定义的错误条件名称;
SQLWARNING:匹配所有以 01 开头的 sqlstate_value 值;
NOT FOUND:匹配所有以 02 开头的 sqlstate_value 值;
SQLEXCEPTION:匹配所有没有被 SQLWARNING 或 NOT FOUND 捕获的 sqlstate_value 值;
mysql_error_code:匹配数值类型错误代码。
对游标案例进行优化:
-- 逻辑:
-- A. 声明游标, 存储查询结果集
-- B. 准备: 创建表结构
-- C. 开启游标
-- D. 获取游标中的记录
-- E. 插入数据到新表中
-- F. 关闭游标
create procedure p11(in uage int)
begin
declare uname varchar(100);
declare upro varchar(100);
declare u_cursor cursor for select name,profession from tb_user where age <= uage;
-- 声明条件处理程序 : 当SQL语句执行抛出的状态码为02000时,将关闭游标u_cursor,并退出
declare exit handler for SQLSTATE '02000' 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,upro;
insert into tb_user_pro values (null, uname, upro);
end while;
close u_cursor;
end;
call p11(30);
存储函数是有返回值的存储过程,存储函数的参数只能是IN类型的。具体语法如下:
CREATE FUNCTION 存储函数名称 ([ 参数列表 ])
RETURNS type [characteristic ...]
BEGIN
-- SQL语句
RETURN ...;
END ;
characteristic说明:在mysql8.0版本中binlog默认是开启的,一旦开启了,mysql就要求在定义存储过程时,需要指定characteristic特性,否则就会报错
- DETERMINISTIC:相同的输入参数总是产生相同的结果。
- NO SQL :不包含 SQL 语句。
- READS SQL DATA:包含读取数据的语句,但不包含写入数据的语句。
案例:计算从1累加到n的值,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(50);