第17章_触发器


在实际开发中,我们经常会遇到这样的情况:有 2 个或者多个相互关联的表,如 商品信息 和 库存信息 分

别存放在 2 个不同的数据表中,我们在添加一条新商品记录的时候,为了保证数据的完整性,必须同时

在库存表中添加一条库存记录。

这样一来,我们就必须把这两个关联的操作步骤写到程序里面,而且要用 事务 包裹起来,确保这两个操

作成为一个 原子操作 ,要么全部执行,要么全部不执行。要是遇到特殊情况,可能还需要对数据进行手

动维护,这样就很 容易忘记其中的一步 ,导致数据缺失。

这个时候,咱们可以使用触发器。你可以创建一个触发器,让商品信息数据的插入操作自动触发库存数

据的插入操作。这样一来,就不用担心因为忘记添加库存数据而导致的数据缺失了。

触发器概述


MySQL从 5.0.2 版本开始支持触发器。MySQL的触发器和存储过程一样,都是嵌入到MySQL服务器的一

段程序。

触发器是由 事件来触发 某个操作,这些事件包括 INSERT 、 UPDATE 、 DELETE 事件。所谓事件就是指

用户的动作或者触发某项行为。如果定义了触发程序,当数据库执行这些语句时候,就相当于事件发生

了,就会 自动 激发触发器执行相应的操作。

当对数据表中的数据执行插入、更新和删除操作,需要自动执行一些数据库逻辑时,可以使用触发器来

实现。

触发器的创建

创建触发器的语法结构是:

CREATE TRIGGER 触发器名称
{BEFORE|AFTER} {INSERT|UPDATE|DELETE} ON 表名
FOR EACH ROW
触发器执行的语句块;

表名 :表示触发器监控的对象。

BEFORE|AFTER :表示触发的时间。BEFORE 表示在事件之前触发;AFTER 表示在事件之后触发。

INSERT|UPDATE|DELETE :表示触发的事件。

INSERT 表示插入记录时触发;

UPDATE 表示更新记录时触发;

DELETE 表示删除记录时触发。

代码举例

创建数据表:

CREATE TABLE test_trigger (
id INT PRIMARY KEY AUTO_INCREMENT,
t_note VARCHAR(30)
);
CREATE TABLE test_trigger_log (
id INT PRIMARY KEY AUTO_INCREMENT,
t_log VARCHAR(30)
);

2、创建触发器:创建名称为before_insert的触发器,向test_trigger数据表插入数据之前,向

test_trigger_log数据表中插入before_insert的日志信息。

DELIMITER //
CREATE TRIGGER before_insert
BEFORE INSERT ON test_trigger
FOR EACH ROW
BEGIN
INSERT INTO test_trigger_log (t_log)
VALUES('before_insert');
END //
DELIMITER ;

3、向test_trigger数据表中插入数据

INSERT INTO test_trigger (t_note) VALUES ('测试 BEFORE INSERT 触发器');

4、查看test_trigger_log数据表中的数据

mysql> SELECT * FROM test_trigger_log;
+----+---------------+
| id | t_log |
+----+---------------+
| 1 | before_insert |
+----+---------------+
1 row in set (0.00 sec)

举例2:

1、创建名称为after_insert的触发器,向test_trigger数据表插入数据之后,向test_trigger_log数据表中插

入after_insert的日志信息。

CREATE TRIGGER after_insert
AFTER INSERT ON test_trigger
FOR EACH ROW
BEGIN
INSERT INTO test_trigger_log (t_log)
VALUES('after_insert');
END //
DELIMITER ;

2、向test_trigger数据表中插入数据。

INSERT INTO test_trigger (t_note) VALUES ('测试 AFTER INSERT 触发器');

3、查看test_trigger_log数据表中的数据

mysql> SELECT * FROM test_trigger_log;
+----+---------------+
| id | t_log |
+----+---------------+
| 1 | before_insert |
| 2 | before_insert |
| 3 | after_insert |
+----+---------------+
3 rows in set (0.00 sec)

举例3:定义触发器“salary_check_trigger”,基于员工表“employees”的INSERT事件,在INSERT之前检查

将要添加的新员工薪资是否大于他领导的薪资,如果大于领导薪资,则报sqlstate_value为'HY000'的错

误,从而使得添加失败。

DELIMITER //
CREATE TRIGGER salary_check_trigger
BEFORE INSERT ON employees FOR EACH ROW
BEGIN
DECLARE mgrsalary DOUBLE;
SELECT salary INTO mgrsalary FROM employees WHERE employee_id = NEW.manager_id;
IF NEW.salary > mgrsalary THEN
SIGNAL SQLSTATE 'HY000' SET MESSAGE_TEXT = '薪资高于领导薪资错误';
END IF;
END //
DELIMITER ;

上面触发器声明过程中的NEW关键字代表INSERT添加语句的新记录。

查看、删除触发器

查看触发器是查看数据库中已经存在的触发器的定义、状态和语法信息等。

方式1:查看当前数据库的所有触发器的定义

SHOW TRIGGERS\G

方式2:查看当前数据库中某个触发器的定义

SHOW CREATE TRIGGER 触发器名

方式3:从系统库information_schema的TRIGGERS表中查询“salary_check_trigger”触发器的信息。

SELECT * FROM information_schema.TRIGGERS;

删除触发器

触发器也是数据库对象,删除触发器也用DROP语句,语法格式如下:

DROP TRIGGER IF EXISTS 触发器名称

触发器的优缺点

优点

1、触发器可以确保数据的完整性

假设我们用 进货单头表 (demo.importhead)来保存进货单的总体信息,包括进货单编号、供货商编

号、仓库编号、总计进货数量、总计进货金额和验收日期。

用 进货单明细表 (demo.importdetails)来保存进货商品的明细,包括进货单编号、商品编号、进货数

量、进货价格和进货金额。

额就不等于进货单明细表中数量合计和金额合计了,这就是数据不一致。

为了解决这个问题,我们就可以使用触发器,规定每当进货单明细表有数据插入、修改和删除的操作

时,自动触发 2 步操作:

1)重新计算进货单明细表中的数量合计和金额合计;

2)用第一步中计算出来的值更新进货单头表中的合计数量与合计金额。

这样一来,进货单头表中的合计数量与合计金额的值,就始终与进货单明细表中计算出来的合计数量与

合计金额的值相同,数据就是一致的,不会互相矛盾。

2、触发器可以帮助我们记录操作日志。

利用触发器,可以具体记录什么时间发生了什么。比如,记录修改会员储值金额的触发器,就是一个很

好的例子。这对我们还原操作执行时的具体场景,更好地定位问题原因很有帮助。

3、触发器还可以用在操作数据前,对数据进行合法性检查。

比如,超市进货的时候,需要库管录入进货价格。但是,人为操作很容易犯错误,比如说在录入数量的

时候,把条形码扫进去了;录入金额的时候,看串了行,录入的价格远超售价,导致账面上的巨亏……

这些都可以通过触发器,在实际插入或者更新操作之前,对相应的数据进行检查,及时提示错误,防止

错误数据进入系统。

缺点

1、触发器最大的一个问题就是可读性差。

因为触发器存储在数据库中,并且由事件驱动,这就意味着触发器有可能 不受应用层的控制 。这对系统

维护是非常有挑战的。

比如,创建触发器用于修改会员储值操作。如果触发器中的操作出了问题,会导致会员储值金额更新失

败。我用下面的代码演示一下:

mysql> update demo.membermaster set memberdeposit=20 where memberid = 2;
ERROR 1054 (42S22): Unknown column 'aa' in 'field list'

结果显示,系统提示错误,字段“aa”不存在。

这是因为,触发器中的数据插入操作多了一个字段,系统提示错误。可是,如果你不了解这个触发器,

很可能会认为是更新语句本身的问题,或者是会员信息表的结构出了问题。说不定你还会给会员信息表

添加一个叫“aa”的字段,试图解决这个问题,结果只能是白费力。

2、相关数据的变更,可能会导致触发器出错

特别是数据表结构的变更,都可能会导致触发器出错,进而影响数据操作的正常运行。这些都会由于触

发器本身的隐蔽性,影响到应用中错误原因排查的效率。

注意点

注意,如果在子表中定义了外键约束,并且外键指定了ON UPDATE/DELETE CASCADE/SET NULL子句,此
时修改父表被引用的键值或删除父表被引用的记录行时,也会引起子表的修改和删除操作,此时基于子
表的UPDATE和DELETE语句定义的触发器并不会被激活。
例如:基于子表员工表(t_employee)的DELETE语句定义了触发器t1,而子表的部门编号(did)字段定
义了外键约束引用了父表部门表(t_department)的主键列部门编号(did),并且该外键加了“ON
DELETE SET NULL”子句,那么如果此时删除父表部门表(t_department)在子表员工表(t_employee)

mysql零基础-3的更多相关文章

  1. mysql 零基础 开始过程

    2016-11-07 算是差不多是两个月的学习,我也马上要结课了.今天才勉强把mysql装上,之前还有因为用户权限的问题,以及用户为创建的问题.应该早点就把该准备的开发平台准备好,而不是在最后快考试了 ...

  2. MySQL数据库 | MySQL调优|MySQL底层原理|MySQL零基础新手教程

    MySQL数据库安装 一.Windows 环境下安装 A.下载 MySQL Select Operating System: Microsoft Windows 快捷下载:mysql-8.0.22-w ...

  3. 只要9.9元!零基础学习MySQL

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 导语 经过一段时间的筹备和整理,万里数据库<零基础学习MySQL>课程正式在腾讯课堂上线了. 课程地址:htt ...

  4. 2020年数据库概念与MySQL的安装与配置-从零基础入门MySQL-mysql8版本

    作者 | Jeskson 来源 | 达达前端小酒馆 从零基础入门MySQL数据库基础课 数据的概念,简介,安装与配置,Windows平台下MySQL的安装与配置. 数据库的概念:数据库是一个用来存放数 ...

  5. 【零基础】搞定LAMP(linux、apache、mysql、php)环境安装图文教程(基于centos7)

    一.前言 LAMP即:Linux.Apache.Mysql.Php,也就是在linux系统下运行php网站代码,使用的数据库是mysql.web服务软件是apache.之所以存在LAMP这种说法,倒不 ...

  6. 零基础如何系统学习Java Web

    零基础如何系统学习Java Web?   我来给你说一说 你要下决心,我要转行做开发,这样你才能学成. 你要会打字,我公司原来有一个程序员,打字都是两个手一指禅,身为程序员你一指禅怎么写出的代码,半个 ...

  7. LNMP系列网站零基础开发记录(一)

    [目录] 扯淡吹逼之开发前奏 Django 开发环境搭建及配置 web 页面开发 Django app开发 Django 站点管理 Python 简易爬虫开发 Nginx&uWSGI 服务器配 ...

  8. Cloudera Manager、CDH零基础入门、线路指导 http://www.aboutyun.com/thread-9219-1-1.html (出处: about云开发)

    Cloudera Manager.CDH零基础入门.线路指导http://www.aboutyun.com/thread-9219-1-1.html(出处: about云开发) 问题导读:1.什么是c ...

  9. 零基础到精通Web渗透测试的学习路线

    小编相信很多新手都会遇到以下几个问题 1.零基础想学渗透怎么入手? 2.学习web渗透需要从哪里开始? 这让很多同学都处于迷茫状态而迟迟不下手,小编就在此贴给大家说一下web渗透的学习路线,希望对大家 ...

  10. 零基础开发一款微信小程序商城

    零基础开发一款微信小程序商城 一个朋友问我能不能帮忙做个商城?我一个完整网页都写不出的 菜鸟程序员,我该怎么拒绝呢?好吧,看在小程序这么火的形势下,我还是答应了!找了个开源项目,差不多花了三天时间搞定 ...

随机推荐

  1. CentOS 7 安装步骤以及初始化

    2. 虚拟机分配的资源 因为用的软件不一样,这里设置方法无法截图,但大至如下: 2CPU/1G内存/200G硬盘 去掉打印机等没用的硬件(macOS要去掉打印机和摄像头) 光盘开始选择空白光盘,不要在 ...

  2. vscode远程连接服务器出现Bad owner or permissions on .ssh/config

    vscode远程连接服务器出现Bad owner or permissions on C:\\Users\USER\.ssh/config 过程试图写入的管道不存在, 原因是vscode的remoto ...

  3. python自动化模块及运维工具

    1. psutil 可以获取系统运行的进程和系统利用率(CPU 内存-)信息 import psutil 2. IPy 是python 第三方处理IP地址模块 from IPy import IP 3 ...

  4. linux并行执行线程

    资料来源: (1) https://www.jianshu.com/p/d8d58846c53f(作者:黄甫一) 1.并行任务较少时: (1) 给需要并行运行的命令行在结尾加上"&& ...

  5. BigDecimal精度等注意事项

    1.BigDecimal运算时尽量传入字符串, 反例: BigDecimal num=new BigDecimal(75); num.multiply(new BigDecimal(0.5)).set ...

  6. 从FGUI中取一张图片并返回一个Sprite

    从Fgui中的图集中取一个图素,把图素用到场景等非UI的地方. 此操作会动态创建一个Sprite对象,效率不好,不适合大量使用. private static Dictionary<string ...

  7. Vulnhub 靶场 BEELZEBUB: 1

    Vulnhub 靶场 BEELZEBUB: 1 前期准备 靶机地址:https://www.vulnhub.com/entry/beelzebub-1,742/ kali攻击机ip:192.168.1 ...

  8. 权昌TSC244条码打印机如何加载数据实现大批量打印呢?

    我公司的TSC TTP-244条码打印机,只会改个名称打一张,怎么样改数据或者是加载数据实现大量打印的呢?   解答:   TSC TTP-244条码打印机,是一款性能不错的桌面型条码打印机,最大打印 ...

  9. Vite项目打包配置详解

    一:vite构建项目 配置base 1.base配置打包公共路径 打开package.json 做项目时可以不去掉 好了,在以上你构建了vite,并配置了最简单的操作后,你准备配置vite.confi ...

  10. 【FPGA学习】根据datasheet编写Verilog驱动(PCF8574 IO扩展板练习)

    在之间的博客中已经讲了如何阅读一本datasheet并编写Verilog驱动代码,而在这篇博客中就加以应用,为PCF8574 IO扩展板编写驱动并观察效果,至于为什么选择这个,一方面是因为这个芯片功能 ...