[MySQL]触发器

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: [MySQL]触发器

1. 触发器概述

MySQL从 5.0.2 版本开始支持触发器。

MySQL的触发器和存储过程一样,都是嵌入到MySQL服务器的一段程序

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

所谓事件就是指用户的动作或者某项行为。如果定义了触发程序,当数据库执行这些语句时候,就相当于事件发生了,就会 自动 激发触发器执行相应的操作。

当对数据表中的数据执行插入、更新和删除操作,需要自动执行一些数据库逻辑时,可以使用触发器来实现。例如,向表1插入某些数据时,同时需要对表2中的数据进行相应的更新操作,可以使用触发器来实现,这样子就不用每次主动写SQL语句来更新表2的数据。

2. 触发器的创建

2.1 创建触发器的语法

CREATE TRIGGER 触发器名称
{BEFORE|AFTER} {INSERT|UPDATE|DELETE} ON 表名
FOR EACH ROW
触发器执行的语句块;
  • 表名 :表示触发器监控的对象。
  • BEFORE|AFTER :表示触发的时间。BEFORE 表示在事件之前触发;AFTER 表示在事件之后触发。
  • INSERT|UPDATE|DELETE:表示触发的事件。
  • INSERT 表示插入记录时触发;
  • UPDATE 表示更新记录时触发;
  • DELETE 表示删除记录时触发。
  • FOR EACH ROW:表示只要有触发器监控的表中的行受影响,触发器都执行,叫行级触发器。oracle触发器中分行级触发器和语句级触发器,可不写 for each row,无论影响多少行都只执行一次。mysql 不支持语句触发器,所以必须写for each row。
  • 触发器执行的语句块 :可以是单条SQL语句,也可以是由BEGIN…END结构组成的复合语句块。

2.2 代码示例

2.2.1 数据表的创建

CREATE DATABASE dbtest;
USE dbtest;
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.2.2 创建触发器

示例一

创建名称为before_insert_test_trigger的触发器,向test_trigger数据表插入数据之前,向test_trigger_log数据表中插入before_insert的日志信息。

# 创建名称为 before_insert_test_trigger 的触发器,向 test_trigger 数据表插入数据之前,向
# test_trigger_log 数据表中插入before_insert的日志信息。
CREATE TRIGGER before_insert_test_trigger
BEFORE INSERT ON test_trigger
FOR EACH ROW
BEGIN
    INSERT INTO test_trigger_log(t_log)
    VALUES ('before insert ...');
END;
# 向test_trigger数据表中插入数据
INSERT INTO test_trigger(t_note)
VALUES ('ZS...');
# 查看数据表中的数据
SELECT * FROM test_trigger;
SELECT * FROM test_trigger_log;

示例二

创建名称为after_insert_test_trigger的触发器,向test_trigger数据表插入数据之后,向test_trigger_log数据表中插入after_insert的日志信息。

# 创建名称为 after_insert_test_trigger 的触发器,向 test_trigger 数据表插入数据之后,
# 向test_trigger_log数据表中插入after_insert的日志信息。
CREATE TRIGGER after_insert_test_trigger
AFTER INSERT ON test_trigger
FOR EACH ROW
BEGIN
    INSERT INTO test_trigger_log(t_log)
    VALUES ('after insert ...');
END;
INSERT INTO test_trigger(t_note)
VALUES ('LS...');
SELECT * FROM test_trigger;
SELECT * FROM test_trigger_log;

示例三

定义触发器“salary_check_trigger”,基于员工表“employees”的INSERT事件,在INSERT之前检查将要添加的新员工薪资是否大于他领导的薪资,如果大于领导薪资,则报sqlstate_value为’HY000’的错误,从而使得添加失败。

# 准备数据表
CREATE TABLE employees
AS
SELECT * FROM atguigudb.employees;
CREATE TABLE department
AS
SELECT * FROM atguigudb.departments;
# 定义触发器“salary_check_trigger”,基于员工表“employees”的INSERT事件,在INSERT之前检查
# 将要添加的新员工薪资是否大于他领导的薪资,如果大于领导薪资,则报sqlstate_value为'HY000'的错
# 误,从而使得添加失败。
CREATE TRIGGER salary_check_trigger
    BEFORE INSERT
    ON employees
    FOR EACH ROW
BEGIN
    # NEW 关键字表示要插入的新的记录
    # 查询领导的薪资
    DECLARE mgr_sal DOUBLE(8, 2) DEFAULT 0;
    SELECT salary
    INTO mgr_sal
    FROM employees
    WHERE employee_id = NEW.manager_id;
    # 判断新纪录的薪资是否大于对应领导的薪资
    IF NEW.salary > mgr_sal THEN
        # 自定义错误
        # SQLSTATE 'HY000' 报错标识,SET MESSAGE_TEXT 设置报错信息
        SIGNAL SQLSTATE 'HY000' SET MESSAGE_TEXT = '薪资高于领导薪资错误';
    END IF;
END;
SELECT salary
FROM employees
WHERE employee_id = 103;
INSERT INTO employees(employee_id, last_name, email, hire_date, job_id, salary,
                      manager_id)
VALUES (300, 'ZS', 'ZS@qq.com', CURDATE(), 'AD_VP',10000,103);

3. 触发器的查看

3.1 查看当前数据库的所有触发器的定义

SHOW TRIGGERS;

3.2 查看当前数据库中某个触发器的定义

SHOW CREATE TRIGGER 触发器名;
SHOW CREATE TRIGGER salary_check_trigger;

3.3 从系统库information_schema的TRIGGERS表中查询

SELECT * FROM information_schema.TRIGGERS;

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

SELECT * FROM information_schema.TRIGGERS
WHERE TRIGGER_NAME LIKE 'salary_check_trigger';

4. 删除触发器

触发器也是数据库对象,删除触发器也用DROP语句。

语法:

DROP TRIGGER IF EXISTS 触发器名称;
DROP TRIGGER IF EXISTS after_insert_test_trigger;
SHOW TRIGGERS;

5. 触发器的优缺点

5.1 优点

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

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

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

5.2 缺点

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

2、相关数据的变更,可能会导致触发器出错。触发器创建时不会执行内部的SQL,触发器被触发时,可能由于内部SQL报错而导致报错。

6. 触发器注意点

注意,如果在子表中定义了外键约束,并且外键指定了ON UPDATE/DELETE CASCADE/SET NULL子句,此时修改父表被引用的键值或删除父表被引用的记录行时,也会引起子表的修改和删除操作,此时基于子表的UPDATE和DELETE语句定义的触发器并不会被激活

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
存储 安全 关系型数据库
2024 Mysql基础与进阶操作系列之MySQL触发器详解(21)作者——LJS[你个小黑子这都还学不会嘛?你是真爱粉嘛?真是的 ~;以后请别侮辱我家鸽鸽]
MySQL触发器的使用场景之数据完整性约束、如何具体创建person的日志表、触发器与存储过程的对比与选择、触发器的性能和注意事项等具体操作详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
4月前
|
存储 关系型数据库 MySQL
MySQL 中的触发器数量之谜
【8月更文挑战第31天】
46 0
|
4月前
|
SQL 数据采集 关系型数据库
|
5月前
|
存储 SQL 关系型数据库
(十四)全解MySQL之各方位事无巨细的剖析存储过程与触发器!
前面的MySQL系列章节中,一直在反复讲述MySQL一些偏理论、底层的知识,很少有涉及到实用技巧的分享,而在本章中则会阐述MySQL一个特别实用的功能,即MySQL的存储过程和触发器。
110 0
|
5月前
|
存储 SQL 数据库
MySQL设计规约问题之为什么要避免使用存储过程、触发器和函数
MySQL设计规约问题之为什么要避免使用存储过程、触发器和函数
|
6月前
|
存储 SQL 关系型数据库
MySQL数据库进阶第四篇(视图/存储过程/触发器)
MySQL数据库进阶第四篇(视图/存储过程/触发器)
|
6月前
|
存储 SQL 关系型数据库
MySQL周内训参照4、触发器-插入-修改-删除
MySQL周内训参照4、触发器-插入-修改-删除
53 1
|
6月前
|
存储 关系型数据库 MySQL
MySQL触发器实战:自动执行的秘密
MySQL触发器实战:自动执行的秘密
138 3
|
6月前
|
存储 SQL 关系型数据库
MySQL 进阶使用【函数、索引、视图、存储过程、存储函数、触发器】(2)
MySQL 进阶使用【函数、索引、视图、存储过程、存储函数、触发器】
|
6月前
|
存储 SQL 关系型数据库
MySQL 进阶使用【函数、索引、视图、存储过程、存储函数、触发器】(1)
MySQL 进阶使用【函数、索引、视图、存储过程、存储函数、触发器】