MySQL触发器的使用

一、前言

     各种主流数据库,都集成了触发器的功能。触发器提供了一种机制,允许开发者在对数据库表的插入、更新、删除的前后捕获相应的数据行。从而针对数据行实现特定的逻辑。结合具体的例子来看,比如有多个应用系统都对数据库某张表进行了插入操作,现在需要对该表的某个字段进行修改。我们可以怎么做呢,如果是倾向于在应用系统中改变逻辑从而实现目标,那么我们就需要同时修改两套应用系统;而如果是倾向于使数据库的话我们只需要针对这个表的相应触发器进行操作即可。显然两者都能达到目的,但是实际的应用场景并不总是如我们所愿。比如应用系统是用c#开发的但是不擅长c#的话就不好轻易的去改动代码,这个时候刚好会数据库,那么触发器就可以派上用场了。还有一点就是我们不知道某个表会被哪些哪些应用系统操作的时候,我们也可以使用触发器来解决问题。总而言之,触发器守住了数据的入口,在某种程度上也提供了一定的便利。
     **触发器类似于事件,创建触发器就是注册事件回调过程的过程**。我们知道,一般事件是被动触发的,而且事件可以形成事件链,触发器也是如此。对于事件一般我们是通过"注册回调函数"这种方式来完成,触发器也是一种"回调函数",只不过这种"回调函数"使用的是数据库支持的语法。一般回调函数都会传入 上下文的变量,我们知道在触发器里有old和new变量,这两个变量就是上下文变量,用来指代更新前后的数据行。

二、触发器分类

    触发器分为插入触发器、更新触发器、删除触发器。这三个触发器都有前置和后置两个动作,也就是插入之前/之后,更新之前/之后,删除之前/之后,对应语法就是BEFORE 和AFTER。
    下面通过mysql触发器的示例来介绍它的使用方法。首先我们创建一张测试表,后面的插入触发器、更新触发器和删除触发器都围绕这张表来说明。
DROP TABLE app_user;
CREATE TABLE app_user(id int primary key AUTO_INCREMENT,username varchar(32),pwd varchar(32));

1.插入触发器

以下代码为表app_user创建了一个前置插入触发器,该触发器的作用将插入到app_user表的数据同步到app_user2表,app_user2表与app_user表具有相同的表结构

CREATE TABLE IF NOT EXISTS app_user2 like app_user;
DROP TRIGGER IF EXISTS trigger_before_insert_app_user;
CREATE TRIGGER trigger_before_insert_app_user BEFORE INSERT ON app_user FOR EACH ROW BEGIN
	insert into app_user2(`id`,`username`,`pwd`) values(new.`id`,new.`username`,new.`pwd`);
END;

使用INSERT INTO往app_user表插入一条数据后之后查看两表数据,可以看到app_user表数据行插入到了app_user2
在这里插入图片描述

2.更新触发器

以下代码为app_user表创建了一个前置更新触发器,该触发器的作用在更新app_user表的同时将app_user2表的记录同步更新

DROP TRIGGER IF EXISTS trigger_before_update_app_user;
CREATE TRIGGER trigger_before_update_app_user BEFORE UPDATE ON app_user FOR EACH ROW BEGIN
	UPDATE app_user2 set 
		`id` = new.`id`,
		`username` = new.`username`,
		`pwd` = new.`pwd`
 	WHERE id=old.id;
END;

**使用UPDATE语句更新app_user表中id=‘1’的记录中字段username值由’test’更新为’test1’ **
可以看到app_user2表记录数据得到了同步更新
在这里插入图片描述
字段username更新前的值是’test’,更新后变成了’test1’,更新之前的值可以通过old变量访问,更新之后的值通过new变量访问,
可以通过微调触发器代码来查看数据,将old和new变量中的username字段进行了拼接并更新到username字段
在这里插入图片描述

然后重新创建更新触发器

DROP TRIGGER IF EXISTS trigger_before_update_app_user;
CREATE TRIGGER trigger_before_update_app_user BEFORE UPDATE ON app_user FOR EACH ROW BEGIN
	UPDATE app_user2 set 
		`id` = new.`id`,
		`username` = concat('old.username:',old.username,' new.username:',new.`username`),
		`pwd` = new.`pwd`
 	WHERE id=old.id;
END;

执行UPDATE语句后可以对比查看old.username和new.username变量的值
在这里插入图片描述

3.删除触发器

以下代码为app_user表创建了一个前置删除触发器,删除app_user表记录的同时同步删除app_user2表记录

DROP TRIGGER IF EXISTS trigger_before_delete_app_user;
CREATE TRIGGER trigger_before_delete_app_user BEFORE DELETE ON app_user FOR EACH ROW BEGIN
	DELETE FROM app_user2 WHERE id=old.id;
END;

在这里插入图片描述

三、查看触发器

使用show triggers命令查看所有触发器
在这里插入图片描述
也可以指定关键字进行模糊查询
在这里插入图片描述

四、异常处理

触发器作为一种特定的"回调函数",它在执行的过程中也会抛出异常。一般编程语言中都有类似的try catch finally来进行异常捕获,
当然mysql也有对应的异常处理机制
出错继续

DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @x = 0;

出错退出

DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @x = 0;

代码段中 SET @x = 0 是出错时的处理程序,这样判断程序是否出错就可以根据x变量的值来判断
我们知道 往主键唯一的表插入重复记录会抛出异常

app_user表 “前置插入触发器” 当前逻辑为

DROP TRIGGER IF EXISTS trigger_before_insert_app_user;
CREATE TRIGGER trigger_before_insert_app_user BEFORE INSERT ON app_user FOR EACH ROW BEGIN
	insert into app_user2(`id`,`username`,`pwd`) values(new.`id`,new.`username`,new.`pwd`);
END;

app_user表和app_user2表的数据分别为
在这里插入图片描述

在不改动逻辑的情况下,插入重复记录的时候,会出现报错
在这里插入图片描述
修改触发器模拟报错场景,比如将insert语句中的id写死为1 ,这样无论往app_user表中插入任何数据都会引发报错
在这里插入图片描述
在这里插入图片描述
那么如何使语句 INSERT INTO app_user(id,username,pwd) values(2,‘test’,‘123’); 成功执行呢
可以修改触发器如下

DROP TRIGGER IF EXISTS trigger_before_insert_app_user;
CREATE TRIGGER trigger_before_insert_app_user BEFORE INSERT ON app_user FOR EACH ROW BEGIN
    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @x = 0;
	insert into app_user2(`id`,`username`,`pwd`) values(1,new.`username`,new.`pwd`);
END;

在这里插入图片描述

在这里插入图片描述
可以看到app_user表有2条记录,app_user表只有1条记录

五、小结

1.使用触发器可以实现表数据的同步,可以用来实现增量数据同步。
2.不管数据是否插入、更新、删除成功,前置触发器都会首先被调用。
3.触发器中有异常也是能够被捕获的。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天水麒麟姜伯约

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值