存储过程
分类
存储例程
本质上也是封装了一些可执行的语句,只不过它的调用方式是显示调用
。存储例程可分为存储函数和存储过程。两者间区别如下:
存储函数 | 存储过程 | |
---|---|---|
return语句 | 必须有 | 可以有 |
返回值个数 | 1个 | >=1个 |
参数类型 | in | in(默认) out inout |
显示 | 执行过程中的select不会显示 | 执行过程中的select会显示 |
调用 | 可以直接在表达式和SQL语句中调用 | 只能用CALL语句显示调用 |
其中,存储过程不需要返回值
,而存储函数必须有返回值
。另外,存储过程在执行查询语句时产生的所有结果集,全部将会被显示到客户端。
存储函数
-
定义
CREATE FUNCTION 存储函数名称([参数名 数据类型]组成的参数列表) comment ‘函数的注释说明’ RETURNS 返回值类型 BEGIN 函数体内容 -- 函数体中,每条语句都要以分号;结尾 -- 函数体内容可以包含: -- 1. SQL语句,如: -- 2. 变量定义(此时变量的定义用declare,不加@)和赋值 DECLARE 变量名 数据类型 [DEFAULT 默认值]; -- 不声明默认值时,默认值为NULL set 变量名 = 变量/值; -- 3. 流程控制语句 -- 3.1 条件语句 if 布尔表达式 then 处理语句 elseif 布尔表达式 then 处理语句 else 处理语句 end if; -- 3.2 循环语句 -- 方式1 while 布尔表达式 do 循环语句 end while; -- 方式2 repeat 循环语句 until 布尔表达式 end repeat; -- 方式3 循环标记:loop 循环语句 leave 循环标记; -- leave语句一般和判断语句一起用,用来退出循环 end loop 循环标记 END
例子:
create function avg_score(s varchar(100)) return double begin declare c int default 1; set c = s; return (select avg(score) from student_score where subject = s) end $
-
调用
自定义的函数和系统内置函数的使用方式是一样的。直接利用
函数名()
即可
-
查看
-- 查看定义的函数有哪些 SHOW FUNCTION STATUS [LIKE 需要匹配的函数名] -- 查看某个函数的具体定义 SHOW CREATE FUNCTION 函数名
-
删除
DROP FUNCTION 函数名
存储过程
-
定义
CREATE PROCEDURE 存储过程名称([参数类型 参数名 数据类型]组成的参数列表) -- 存储过程的参数类型有三种:in out inout -- in:实参可为常量/变量;实参为变量时,只能向外赋值,不能被赋值(即in型参数的值不会被存储过程更改) -- out:实参只能是变量;实参不能向外赋值,只能被赋值 -- inout:实参只能是变量;实参既可向外赋值,又可被赋值 BEGIN 需要执行的语句,可包含内容和存储函数是一样的。 END
例子:
create procedure t1_operation(m1_value int, n1_value char(1)) begin select * from t1; insert into t1(m1,n1) values(m1_value,n1_value); select * from t1; end $
-
调用
call 存储过程([参数列表]);
-
查看
-- 查看定义的存储过程有哪些 SHOW PROCEDURE STATUS [LIKE 需要匹配的函数名] -- 查看某个存储过程的详细定义 SHOW CREATE PROCEDURE 存储过程名称
-
删除
DROP PROCEDURE 存储过程名称
触发器
触发器的作用就是,在对某个表格进行某项操作(增删改)之前或之后,自动地
(即被服务器隐性调用)对操作所涉及的记录
执行触发器操作。
-
定义
-- 竖线"|"分隔的语句表示必须在给定的选项中选取一个值 CREATE TRIGGER 触发器名 {BEFORE|AFTER} {INSERT|DELETE|UPDATE} ON 表名 FOR EACH ROW BEGIN 触发器操作 END
CREATE TRIGGER 触发器名
触发器名字一般的命名规则为:“b/a”+“i/d/u”+"_"+“表名”,例如 bi_t1 ,表示对表 t1 设置 before insert 类型的触发器。
BEFORE AFTER
INSERT DELETE UPDATE
MySQL中目前只支持对INSERT、DELETE、UPDATE这三种类型的语句设置触发器。
FOR EACH ROW
表示触发器作用范围为
增删改操作涉及的记录
- 对于INSERT,FOR EACH ROW影响的记录就是我们准备插入的那些新记录。
- 对于DELETE和UPDATE,FOR EACH ROW影响的记录就是符合WHERE条件的那些记录(如果语句中没有WHERE条件,那就是代表全部的记录)。
BEGIN ... END
表示触发器需要执行的操作。其中,
不能有输出结果集相关的语句
,如select。此外,触发器使用
"new"
和"old"
来表示原表中不存在和已存在的记录。其中,- 对于INSERT语句设置的触发器来说,
NEW
代表准备插入的记录,不会使用OLD
。 - 对于DELETE语句设置的触发器来说,
OLD
代表删除前的记录,不会使用NEW
。 - 对于UPDATE语句设置的触发器来说,
NEW
代表修改后的记录,OLD
代表修改前的记录。
例子:
create trigger bi_ti before insert on t1 for each row begin if new.m1<1 then set new.m1 =1; elseif new.m1>10 then set new.m1 = 10; end if; end $
-
调用
触发器的调用,在对表格执行增删改操作时,
自动
执行。 -
查看
-- 查看数据库中有哪些触发器 show triggers -- 查看某个触发器的定义 show create trigger 触发器名;
-
删除
drop trigger 触发器名;
事件
事件可以实现,自动地
(即被服务器隐性调用)在某个时间点
或者某隔一段时间
执行一次某些命令。
-
定义
CREATE EVENT 事件名 ON SCHEDULE {AT 某个确定的时间点 | EVERY 期望的时间间隔 [STARTS datetime][END datetime]} DO BEGIN 具体的语句 END
例子:
-- 指定某个时间点执行 CREATE EVENT insert_t1 ON SCHEDULE AT '2018-03-10 15:48:54' -- 也可以写成:AT DATE_ADD(NOW(), INTERVAL 2 DAY) DO BEGIN INSERT INTO t1(m1, n1) VALUES(6, 'f'); END -- 指定某个时间间隔执行 CREATE EVENT insert_t1 ON SCHEDULE EVERY 1 HOUR STARTS '2018-03-10 15:48:54' ENDS '2018-03-12 15:48:54' -- 也可以写成:EVERY 1 HOUR DO BEGIN INSERT INTO t1(m1, n1) VALUES(6, 'f'); END
-
调用
事件会被服务器,在相应的时间设定下,被自动调用。
事件的自动调用需要在服务器中开启:
-- 启动mysql服务器时,开启事件监听 event_scheduler = ON -- 开启mysql服务器后,通过设置mysql服务器的环境变量,开启事件监听 set global event_scheduler = ON
-
查看
-- 查看数据库定义的事件 SHOW EVENTS; -- 查看某个事件具体创建命令 SHOW CREATE EVENT 事件名;
-
删除
DROP EVENT 事件名;
游标
类似于迭代器,用来标记
结果集中正在访问的某一行记录
,初始状态下它标记结果集中的第一条记录,每次使用后自动移动到下一条记录的位置。
游标可以用在存储函数中和存储过程中时,游标的创建、打开、调用和关闭,均在存储函数和存储过程中完成。
-
创建
DECLARE 游标名称 CURSOR FOR 查询语句; -- 注意,创建游标的语句必须放在变量声明的后面
-
打开
打开游标意味着执行查询语句,让创建好的游标与该查询语句得到的结果集关联起来。
open 游标名称;
-
调用
把指定游标对应记录的各列的值依次赋值给
INTO
后边的各个变量。赋值后,游标自动移动到下一条记录
的位置。-- fetch语句一般用在循环语句中 FETCH 游标名 INTO 变量1, 变量2, ... 变量n
-
关闭
关闭游标意味着会释放该游标占用的内存。
close 游标名称;
-
例子
CREATE PROCEDURE cursor_demo() BEGIN -- 声明变量 DECLARE m_value INT; DECLARE n_value CHAR(1); DECLARE not_done INT DEFAULT 1; -- 声明游标 DECLARE t1_record_cursor CURSOR FOR SELECT m1, n1 FROM t1; -- 在游标遍历完记录的时候将变量 not_done 的值设置为 0,并且继续执行后边的语句 DECLARE CONTINUE HANDLER FOR NOT FOUND SET not_done = 0; -- 打开游标 OPEN t1_record_cursor; WHILE not_done = 1 DO -- 使用游标 FETCH t1_record_cursor INTO m_value, n_value; SELECT m_value, n_value, not_done; END WHILE; CLOSE t1_record_cursor; END
参考文献
https://mp.weixin.qq.com/s?__biz=MzIxNTQ3NDMzMw==&mid=2247483968&idx=1&sn=08a4072e046cc7833b60cc9d66298ec8&scene=19#wechat_redirect 存储程序(二)之存储函数简介
https://mp.weixin.qq.com/s?__biz=MzIxNTQ3NDMzMw==&mid=2247483972&idx=1&sn=4b9cc8c88eea19fd726fc61738d7acea&scene=19#wechat_redirect 存储程序(三)之存储过程简介
https://mp.weixin.qq.com/s?__biz=MzIxNTQ3NDMzMw==&mid=2247483976&idx=1&sn=f39ffa2f4388f1f6b593bfeb1094c5a4&scene=19#wechat_redirect 存储程序(四)之游标简介
https://mp.weixin.qq.com/s?__biz=MzIxNTQ3NDMzMw==&mid=2247483980&idx=1&sn=3a3811cf19fadf87f326ad71c3b6f20a&scene=19#wechat_redirect 存储程序(五)之触发器和事件简介
https://www.cnblogs.com/aixinyiji/p/11038635.html MYSQL中的异常处理