MySQL游标和触发器

发布时间 2023-06-07 17:25:50作者: 、怪咖

游标

1、概念

  • 游标是指一个“箭头”指向数据,指向哪个数据就操作哪个数据

2、使用游标

-- 创建存储过程
create procedure p_yb()
begin
	declare empno integer;
	declare ename varchar(256);
	declare result varchar(4000) default '';
	
	-- 定义游标cursor_emp,针对于select语句
	declare cursor_emp cursor for select e.empno,e.ename from emp e;
	-- 设置超限empno=null,循环终止条件,SQLSTATE为02000表示找不到数据了
	declare continue handler for SQLSTATE '02000' set empno = null;
	-- 打开游标
	open cursor_emp;
	-- 游标指向数据存入两个变量
	fetch cursor_emp into empno,ename;
	while(empno is not null) do
		-- 拼接结果
		set result =concat(result,'empno:',empno,'ename:',ename,';');
		fetch cursor_emp into empno,ename;
	end while;
	-- 关闭游标
	close cursor_emp;
	select result;
end;

-- 调用存储过程
call p_yb();

触发器

1、简介

  • 触发器与数据表关系密切,主要用于保护表中的数据。
  • 特别是当有多个表具有一定的相互联系的时候,触发器能够让不同的表保持数据的一致性
  • 在MySQL中,只有执行insert,update,delete操作时才能激活触发器

2、优缺点

  • 优点
    • 触发器的执行是自动的,当对触发器相关表的数据做出相应的修改后立即执行
    • 触发器可以实施比foreign key约束,check 约束更为复杂的检查和操作
    • 触发器可以实现表数据的级联更改,在一定程度上保证了数据的完整性
  • 缺点
    • 使用触发器实现的业务逻辑在出现问题时很难进行定位,特别是涉及到多个触发器的情况下,会使后期维护变得困难
    • 大量使用触发器容易导致代码结构被打乱,增加了程序的复杂性
    • 如果需要变动的数据量较大时,触发器的执行效率会非常低

3、类型

  • insert触发器
    • 在insert语句执行之前或之后响应的触发器
    • 在insert触发器代码内,可引用一个名为new的虚拟表来访问被插入的行
  • update触发器
    • 在update触发器代码内,可引用一个名为new的虚拟表来访问更新的值
    • 在update触发器代码内,可引用一个名为old的虚拟表来访问update语句执行前的值
    • 在before update 触发器内,new中的值可能也被更新,即允许更改将要用于update语句中的值
    • old中的值全部是只读的,不能被更新
  • delete触发器
    • 在delete触发器代码内,可以引用一个名为old的虚拟表来访问被删除的行
    • old中的值全部是只读,不能被更新
  • 对于事务性表,如果触发程序失败,以及由此导致的整个语句失败,那么该语句所执行的所有更改将回滚
  • 对于非事务性表,则不能执行此类回滚,即使语句失败,失败之前所做的任何更改依然有效

4、使用

before触发器

-- 创建触发器,每次将新增薪资记录到一个局部变量中
create trigger tr_salsum
before insert on emp
for each row
set @sum=@sum+new.sal;
-- 查看触发器的作用
set @sum=0;
insert into 'emp' values('9999','xiaoming','CLERK','7782','1982-01-23','1300',null,'10');
select @sum

after触发器

-- 首先创建一张相同的表
create table dept_copy as select * from dept;
-- 向dept插入数据的时候,也会向复制表中插入数据
create trigger tr_chinaloc
after insert on dept
for each row
insert into dept_copy
values(new.deptno,new.dname,concat('china-',new.loc));

--测试
insert into dept values(88,'shop','sh');

5、查看

  • show triggers;

  • 指定触发器

    select * from information_schema.triggers where trigger_name='tr_chinaloc';

6、修改删除

  • 修改触发器可以通过删除原触发器,再以相同的名称创建新的触发器

  • 删除一个表的同时,也会自动删除该表上的触发器

  • 触发器不能更新或覆盖,为了修改一个触发器,必须先删除它,再重新创建

  • drop trigger [if exists] [数据库名]<触发器名>

    drop trigger if exists tr_chinaloc