🐒自己重新梳理一遍,也是一个消化的过程。学习一定要注重输入和输出,如果只输入的话,很多时候只是大脑此刻懂了,但并未记住。这样在实际做题或应用时,就无从下笔了。
存储过程和存储函数可以将复杂的SQL逻辑封装在一起,应用程序无需关注存储过程和函数内部复杂的SQL逻辑,只需要简单地调用存储过程和函数即可。
思想
预先编译的SQL语句的封装执行过程
优点:
缺点:
使用
存储过程没有返回值
DELIMITER $ -- 新的结束标记
CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型, IN|OUT|INOUT 参数名 参数类型, ...)
[characteristics ...] -- 存储过程的约束条件
--LANGUAGE SQL
--| [NOT] DETERMINISTIC
--| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
--| SQL SECURITY { DEFINER | INVOKER } -- 安全级别(定义者可以调用 | 有权限就可以调用),默认为DEFINER
--| COMMENT 'string'
BEGIN
查询语句
END $
DELIMITER ; -- 恢复结束标记
$、//SET:赋值语句,对变量进行赋值。SELECT INTO:将赋值语句的查询结果存放到变量中,也就是为变量赋值。①没有参数(无参数无返回)
②IN(由参数无返回)
③OUT(无参数有返回)
④IN和OUT(有参数有返回)
⑤INOUT(有参数有返回)
CALL 存储过程名(实参列表)
①查看存储过程的创建信息
SHOW CREATE PROCEDURE 存储过程名
②查看存储过程的状态信息
SHOW PROCEDURE STATUS [LIKE '...']

ALTER PROCEDURE 存储函数名
DROP PROCEDURE IF EXIST 存储函数名;
用于查询
有且仅有一个返回值
DELIMITER //
CREATE FUNCTION 存储函数名(参数名, 参数类型)
RETURNS 返回值类型
# 为了避免报错,需要加上下面三行
DETERMINISTIC --
CONTAINS SQL -- 包含SQL
READS SQL DATA
BEGIN
RETURN(SELECT查询语句);
END //
DELIMITER; --把结束符号重新设为`;`
或
# 为避免报错,需要加这一句
SET GLOBAL log_bin_trust_function_creators = 1;
DELIMITER //
CREATE FUNCTION 存储函数名(参数名1 参数类型, 参数名2 参数类型, ...)
RETURNS 返回值类型
BEGIN
RETURN(SELECT查询语句);
END //
DELIMITER; --把结束符号重新设为`;`
SELECT 存储函数名(); -- 调用函数
SET @emp_id := 102; -- 定义变量
# SET @emp_id = 102; `:=`和`=`都可以
SELECT 存储函数名(@emp_id); --调用函数
巧记:因为
存储函数适用于查询,所以调用它也用SELECT。
①查看存储函数的创建信息
SHOW CREATE FUNCTION 存储函数名
②查看存储函数的状态信息
SHOW FUNCTION STATUS [LIKE '...']
ALTER FUNCTION 存储函数名
DROP FUNCTION IF EXIST 存储函数名;
两种赋值符号都可以,效果一样
=:=系统变量用@@开头
两种默认值
my.iniMySQL配置文件中的参数值修改系统变量的值
SET命令重新设置系统变量的值。my.iniMySQL配置文件,继而修改MySQL系统变量的值(该方法需要重启MySQL服务)默认为会话系统变量
global关键字
max_connections:只能是全局系统变量,限制服务器的最大连接数SHOW GLOBAL VARIABLES;SHOW GLOBAL VARIABLES LIKE '%标识符%';SELECT @@global.变量名;为全局变量赋值
SELECT @@global.变量名;
SET GLOBAL 变量名=变量值;
SELECT @@global.变量名;
SET @@global.变量名=变量值;
session关键字
会话系统变量的初始值是全局系统变量值的复制。
pseudo_thread_id:作用于只能是当前会话,用于标记当前会话的MySQL连接ID。
查看所有会话变量SHOW SESSION VARIABLES;或SHOW VARIALBLES;(因为变量默认是会话系统变量)
查看满足条件的部分会话变量SHOW SESSION VARIABLES LIKE '%标识符%';
查看指定会话变量SELECT @@session.变量名;或SELECT @@变量名;
为会话变量赋值
SELECT @@session.变量名;
SET SESSION 变量名=变量值;
SELECT @@session.变量名;
SET @@session.变量名=变量值;
用户自定义变量用@开头:会话用户变量(不用指明类型),局部变量(需要指明类型)
定义与赋值(需要加@,不需要指定类型)
1.手动赋值
SET @用户变量 = 值;
SET @用户变量 := 值;
2.赋表中的字段值
SELECT @用户变量 := 表达式 [FROM 等字句];
SELECT 表达式 INTO @用户变量 [FROM 等字句];
作用域
只对当前会话有效
可以加在会话的任何地方
查看用户变量
SELECT @用户变量
定义(需要指定类型)
DECLARE 局部变量名 类型 [default 值];
# 如果没有default子句,初始值为NULL
赋值(不需要加@)
1.手动赋值
SET 变量名=值
SET 变量名:=值
2.赋表中的字段值
SELECT 字段名或表达式 INTO 变量名 FROM 表;
作用域
只在BEGIN和END语句块中有效,且只能放在第一句。
只能在存储过程和函数中使用
使用变量
SELECT 局部变量名
DELIMITER //
CLEAR PROVEDURE/FUNCTION 存储过程名/存储函数名
BEGIN
# 声明局部变量
DECLARE 局部变量名 类型 DEFAULT 默认值;
# 为局部变量赋值
SET 局部变量名 = 值;
SELECT 字段名 INTO 局部变量名 FROM 表名 WHERE 筛选条件;
# 查看局部变量的值
SELECT 变量1, 变量2, ...;
END
DELIMITER ;
为了避免程序一报错就停止运行,可以实现将可能发生的错误列出来,当错误出现时,只用报相应的错误代码,而保证程序能够顺利执行完毕。
即:给实现定义程序执行过程中可能遇到的问题命名。将一个错误名字和指定的错误条件关联起来。
# MySQL_error_code
DECLARE 错误名 CONDITION FOR 数值类型错误码
# sqlstate_value
DECLARE 错误名 CONDITION FOR SQLSTATE 字符串类型错误码
例:在ERROR 1418(HY000)中:
1418是MySQL_error_code(数值类型错误代码),
HY000是sqlstate_value(长度为5的字符串类型错误代码)
DECLARE field_Not_Be_NULL CON
即:定义在遇到问题时应当采取的处理方式,保证存储过程或函数在遇到警告或错误时能继续执行。
DECLARE 处理方式 HANDLER FOR 错误类型 处理语句
处理方式
CONTINUE:遇到错误不处理,继续执行。EXIT:遇到错误马上退出错误类型
SQLSTATE ‘字符串错误码’:表示长度为5的sqlstate_value类型的错误代码MySQL_error_code:匹配数值类型错误代码错误名称:表示DECLARE...CONDITION定义的错误条件名称SQLWARNING :匹配所有以01开头的SQLSTATE错误代码;NOT FOUND :匹配所有以02开头的SQLSTATE错误代码;SQLEXCEPTION :匹配所有没有被SQLWARNING或NOT FOUND捕获的SQLSTATE错误代码;处理语句
SET 变量 = 值
BEGIN...END
定义处理程序的几种方式,代码如下:
#方法1:捕获sqlstate_value
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info = 'NO_SUCH_TABLE';
#方法2:捕获mysql_error_value
DECLARE CONTINUE HANDLER FOR 1146 SET @info = 'NO_SUCH_TABLE';
#方法3:先定义条件,再调用
DECLARE no_such_table CONDITION FOR 1146;
DECLARE CONTINUE HANDLER FOR NO_SUCH_TABLE SET @info = 'NO_SUCH_TABLE';
#方法4:使用SQLWARNING
DECLARE EXIT HANDLER FOR SQLWARNING SET @info = 'ERROR';
#方法5:使用NOT FOUND
DECLARE EXIT HANDLER FOR NOT FOUND SET @info = 'NO_SUCH_TABLE';
#方法6:使用SQLEXCEPTION
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info = 'ERROR';
IF CASE用在BEGIN...END中
DELIMITER //
CREATE PROCEDURE/FUNCTION 存储过程名/存储函数名()
[标记名:]BEGIN
IF ...
THEN ... -- LEAVE 标记名
ELSEIF ...
THEN ...
ELSE
END IF;
END //
DELIMITER ;
用于BEGIN...END中
情况1(类似与switch)
CASE 表达式
WHEN 值1 THEN 结果1或语句1(语句1的结尾要加;)
WHEN 值2 THEN 结果2或语句2(语句1的结尾要加;)
...
ELSE 结果n或语句n(语句n的结尾要加;)
END CASE
情况2(类似于多重IF)
CASE
WHEN 条件1 THEN 结果1或语句1(语句1的结尾要加;)
WHEN 条件2 THEN 结果2或语句2(语句1的结尾要加;)
...
ELSE 结果n或语句n(语句n的结尾要加;)
END CASE
LOOP WHILE REPEAT三种循环都可以省略名称。
但如果循环中添加了循环控制语句(LEAVE或ITERATE),则必须添加名称。
DELIMITER //
CREATE PROCEDURE/FUNCTION 存储过程名/存储函数名()
BEGIN
# 定义变量,用于记录循环次数
DECLARE loop_count INT DEFAULT 0;
# ①初始化循环条件
SELECT ...
[标记名:]Loop
# ②循环条件(何时结束循环)
[IF ... THEN LEAVE [标记名];
END IF;]
[IF ... THEN ITERATE [标记名];
END IF;]
# ③循环体——循环要完成的任务
... -- 根据题目要求写
# ④迭代条件
...; -- 重新计算循环条件(与初始化循环条件一致)
SET loop_count = loop_count +1; -- 循环次数+1
END LOOP loop名;
END //
DELIMITER ;
DELIMITER //
CREATE PROCEDURE/FUNCTION 存储过程名/存储函数名()
BEGIN
# ①初始化循环条件
# ②循环条件
[标记名]:WHILE 循环条件 DO
# ③循环体
# ④迭代条件
[IF ...
LEAVE 标记名;
END IF;]
END WHILE;
END //
DELIMITER ;
DELIMITER //
CREATE PROCEDURE/FUNCTION 存储过程名/存储函数名()
BEGIN
REPEAT
循环
UNTIL -- 结束循环的条件。注意:这句没有`;`
END REPEAT;
END //
DELIMITER ;
ITERATE LEAVELEAVE类似于breakLEAVE 标记名
ITERATE类似于continue只能用在LOOP/REPEAT/WHILE循环语句中
ITERATE 标记名
事件:用户的动作或触发某项行为,包括INSERT, UPDATE, DELETE。
当执行INSERT, UPDATE, DELETE事件时,会自动激发触发器执行相应的操作。
DELIMITER //
CREATE TRIGGER 触发器名称
{BEFORE|AFTER} {INSERT|UPDATE|DELETE} ON 表名 -- `表名`为触发器监控的对象
FOR EACH ROW
BEGIN
触发器执行的语句块;
-- VALUE(NEW.字段名)
-- VALUE(OLD.字段名)
END //
DELIMITER ;
BEFORE 表示在事件之前触发AFTER 表示在事件之后触发INSERT 表示插入记录时触发UPDATE 表示更新记录时触发DELETE 表示删除记录时触发NEW关键字用于调用最新插入的数据(用在触发器执行的语句块的VALUE语句中,如VALUE(NEW.字段名)可用于查看该字段最新插入的数据值。)OLD关键字用于调用最近删除的数据(用在触发器执行的语句块的VALUE语句中,如VALUE(OLD.字段名)可用于查看该字段最近删除的数据值。)验证触发器是否起作用
注:与上方创建触发器的代码中的BEGIN...END中对应
BEGIN
触发器执行的语句块这个语句块可用于将触发后的操作记录在
指定表中。
.
这样,当被触发器监控的对象触发操作时,这个指定表就会记录相应的内容。
.
通过SELECT * FROM 指定表;,可以查看是否触发了触发器。
END
所有触发器的定义SHOW TRIGGERS某个触发器的定义SHOW CREATE TRIGGER 触发器名information_schema的TRIGGER表中查询“salary_check_trigger”触发器的信息SELECT * FROM information_schema.TRIGGERS;DROP TRIGGER IF EXISTS 触发器名称
优点
缺点
触发器不会被激活。