数据库组成 触发器
17.1 创建触发器
MySQL中创建触发器可以使用CREATE TRIGGER语句。MySQL中的触发器可以包含一条执行语句,也可以包含多条执行语句。
17.1.1 语法格式
创建触发器的语法格式如下:
CREATE
[DEFINER = user]
TRIGGER trigger_name
trigger_time trigger_event
ON tbl_name FOR EACH ROW
[trigger_order]
trigger_body
语法格式说明如下:
·trigger_name:创建的触发器的名称。
·trigger_time:标识什么时候执行触发器,支持两个选项,分别为BEFORE和AFTER。其中,BEFORE表示在某个事件之前触发,AFTER表示在某个事件之后触发。
·trigger_event:触发的事件,支持INSERT、UPDATE和DELETE操作。
·tbl_name:数据表名称,表示在哪张数据表上创建触发器。
·trigger_body:触发器中执行的SQL语句,可以有一条SQL语句,也可以是多条SQL语句。
17.1.2 创建触发器示例
触发器可以在某个事件发生之前触发,也可以在某个事件发生之后触发。
1.创建测试数据表
创建数据表test_trigger和test_trigger_log。
mysql> CREATE TABLE test_trigger (
-> id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
-> t_note VARCHAR(30)
-> );
Query OK, 0 rows affected (0.12 sec)
mysql> CREATE TABLE test_trigger_log (
-> id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
-> t_log VARCHAR(30)
-> );
Query OK, 0 rows affected (0.01 sec)
SQL语句执行成功,接下来对test_trigger数据表进行增加、删除和修改操作,使用触发器将test_trigger数据表中的数据变化日志写入test_trigger_log数据表中。
2.BEFORE INSERT触发器
例如,创建名称为before_insert的触发器,向test_trigger数据表插入数据之前,向test_trigger_log数据表中插入before_insert的日志信息。
mysql> DELIMITER $$
mysql> CREATE TRIGGER before_insert
-> BEFORE INSERT ON test_trigger
-> FOR EACH ROW
-> INSERT INTO test_trigger_log
-> (t_log)
-> VALUES
-> ('before_insert')
-> ;
-> $$
Query OK, 0 rows affected (0.16 sec)
mysql> DELIMITER ;
SQL语句执行成功,向test_trigger数据表中插入数据。
mysql> INSERT INTO test_trigger (t_note) VALUES ('测试 BEFORE INSERT 触发器');
Query OK, 1 row affected (0.00 sec)
SQL语句执行成功,查看test_trigger数据表中的数据。
mysql> SELECT * FROM test_trigger;
+----+--------------------------------+
| id | t_note |
+----+--------------------------------+
| 1 | 测试 BEFORE INSERT 触发器 |
+----+--------------------------------+
1 row in set (0.01 sec)
向test_trigger数据表中成功插入了一条数据。
查看test_trigger_log数据表中的数据。
mysql> SELECT * FROM test_trigger_log;
+----+---------------+
| id | t_log |
+----+---------------+
| 1 | before_insert |
+----+---------------+
1 row in set (0.00 sec)
向test_trigger数据表插入数据之前,执行触发器向test_trigger_log数据表中插入了before_insert信息。
3.创建AFTER INSERT触发器
例如,创建名称为after_insert的触发器,向test_trigger数据表插入数据之后,向test_trigger_log数据表中插入after_insert的日志信息。
mysql> DELIMITER $$
mysql> CREATE TRIGGER after_insert
-> AFTER INSERT ON test_trigger
-> FOR EACH ROW
-> BEGIN
-> INSERT INTO test_trigger_log
-> (t_log)
-> VALUES
-> ('after_insert');
-> END;
-> $$
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER ;
向test_trigger数据表中插入数据。
mysql> INSERT INTO test_trigger (t_note) VALUES ('测试 AFTER INSERT 触发器');
Query OK, 1 row affected (0.00 sec)
SQL语句执行成功,查看test_trigger数据表中的数据。
mysql> SELECT * FROM test_trigger;
+----+--------------------------------+
| id | t_note |
+----+--------------------------------+
| 1 | 测试 BEFORE INSERT 触发器 |
| 2 | 测试 AFTER INSERT 触发器 |
+----+--------------------------------+
2 rows in set (0.00 sec)
查看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)
test_trigger_log数据表中插入了一条before_insert信息和一条after_insert信息,这是因为此时的数据库中存在before_insert触发器和after_insert触发器,当向test_trigger数据表中插入数据时,会先执行before_insert触发器向test_trigger_log数据表中插入数据,再执行after_insert触发器向test_trigger_log数据表中插入数据,所以会向test_trigger_log数据表中插入两条数据。
注意:BEFORE/AFTER UPDATE触发器和BEFORE/AFTER DELETE触发器的创建方式与BEFORE/AFTER INSERT触发器的创建方式相同,此处不再赘述。
17.2 查看触发器
MySQL中支持使用SHOW TRIGGERS和SHOW CREATE TRIGGER语句查看触发器的信息。同时,在MySQL中会将触发器的信息存储在information_schema数据库中的triggers数据表中,所以也可以在trigger数据表中查看触发器的信息。
17.2.1 使用SHOW TRIGGERS语句查看触发器的信息
使用SHOW TRIGGERS语句查看触发器的信息,语法格式如下:
SHOW TRIGGERS
[{FROM | IN} db_name]
[LIKE 'pattern' | WHERE expr]
·SHOW TRIGGERS:查看触发器的信息的SQL关键字。
·[{FROM | IN} db_name]:{FROM | IN}表示从哪个数据库中查看触发器。db_name表示数据库名称;此项可以省略,当省略时,查看的是当前MySQL命令行所在的数据库的触发器信息。
·[LIKE 'pattern' | WHERE expr]:查看触发器时匹配的条件语句。
例如,查看当前MySQL命令行所在数据库下的触发器信息。
mysql> SHOW TRIGGERS \G
*************************** 1. row ***************************
Trigger: before_insert
Event: INSERT
Table: test_trigger
Statement: INSERT INTO test_trigger_log
(t_log)
VALUES
('before_insert')
Timing: BEFORE
Created: 2019-12-26 22:30:44.31
sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_
DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
Definer: root@localhost
character_set_client: utf8mb4
collation_connection: utf8mb4_general_ci
Database Collation: utf8mb4_0900_ai_ci
*************************** 2. row ***************************
Trigger: after_insert
Event: INSERT
Table: test_trigger
Statement: BEGIN
INSERT INTO test_trigger_log
(t_log)
VALUES
('after_insert');
END
Timing: AFTER
Created: 2019-12-26 22:41:57.51
sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_
DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
Definer: root@localhost
character_set_client: utf8mb4
collation_connection: utf8mb4_general_ci
Database Collation: utf8mb4_0900_ai_ci
################此处省略n行代码##########################
6 rows in set (0.00 sec)
结果显示出了MySQL命令行当前数据库下的所有触发器信息,并显示了每个触发器的名称、事件、触发器所在的数据表和触发器执行时触发的SQL语句等信息。
17.2.2 使用SHOW CREATE TRIGGER语句查看触发器的信息
使用SHOW CREATE TRIGGER语句查看触发器的信息,语法格式如下:
SHOW CREATE TRIGGER trigger_name
其中,trigger_name表示触发器的名称。
例如,查看名称为before_insert触发器的信息。
mysql> SHOW CREATE TRIGGER before_insert \G
*************************** 1. row ***************************
Trigger: before_insert
sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_
FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
SQL Original Statement: CREATE DEFINER=`root`@`localhost` TRIGGER `before_insert` BEFORE INSERT ON
`test_trigger` FOR EACH ROW INSERT INTO test_trigger_log
(t_log)
VALUES
('before_insert')
character_set_client: utf8mb4
collation_connection: utf8mb4_general_ci
Database Collation: utf8mb4_0900_ai_ci
Created: 2019-12-26 22:30:44.31
1 row in set (0.44 sec)
查看结果中显示了触发器的名称、执行触发器时触发的SQL语句。
17.2.3 通过查看triggers数据表中的数据查看触发器的信息
在MySQL中,会将触发器的信息存储到information_schema数据库中的triggers数据表中。可以通过查看information_schema数据库中triggers数据表中的数据来查看触发器的信息。
语法格式如下:
SELECT * FROM information_schema.triggers
WHERE condition
例如,查看名称为before_insert的触发器信息。
mysql> SELECT * FROM information_schema.triggers WHERE trigger_name = 'before_insert' \G
*************************** 1. row ***************************
TRIGGER_CATALOG: def
TRIGGER_SCHEMA: goods
TRIGGER_NAME: before_insert
EVENT_MANIPULATION: INSERT
EVENT_OBJECT_CATALOG: def
EVENT_OBJECT_SCHEMA: goods
EVENT_OBJECT_TABLE: test_trigger
ACTION_ORDER: 1
ACTION_CONDITION: NULL
ACTION_STATEMENT: INSERT INTO test_trigger_log
(t_log)
VALUES
('before_insert')
ACTION_ORIENTATION: ROW
ACTION_TIMING: BEFORE
ACTION_REFERENCE_OLD_TABLE: NULL
ACTION_REFERENCE_NEW_TABLE: NULL
ACTION_REFERENCE_OLD_ROW: OLD
ACTION_REFERENCE_NEW_ROW: NEW
CREATED: 2019-12-26 22:30:44.31
SQL_MODE: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_
FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
DEFINER: root@localhost
CHARACTER_SET_CLIENT: utf8mb4
COLLATION_CONNECTION: utf8mb4_general_ci
DATABASE_COLLATION: utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
查看结果中显示了before_insert触发器所在的数据库、数据表、触发器名称、事件类型和执行触发器时触发的SQL语句等信息。
当不指定条件时,会查询所有的触发器信息。
mysql> SELECT * FROM information_schema.triggers \G
*************************** 1. row ***************************
TRIGGER_CATALOG: def
TRIGGER_SCHEMA: sys
TRIGGER_NAME: sys_config_insert_set_user
EVENT_MANIPULATION: INSERT
EVENT_OBJECT_CATALOG: def
EVENT_OBJECT_SCHEMA: sys
EVENT_OBJECT_TABLE: sys_config
ACTION_ORDER: 1
ACTION_CONDITION: NULL
ACTION_STATEMENT: BEGIN
IF @sys.ignore_sys_config_triggers != true AND NEW.set_by IS NULL THEN
SET NEW.set_by = USER();
END IF;
END
ACTION_ORIENTATION: ROW
ACTION_TIMING: BEFORE
ACTION_REFERENCE_OLD_TABLE: NULL
ACTION_REFERENCE_NEW_TABLE: NULL
ACTION_REFERENCE_OLD_ROW: OLD
ACTION_REFERENCE_NEW_ROW: NEW
CREATED: 2019-11-24 12:46:55.84
SQL_MODE: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_
FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
DEFINER: mysql.sys@localhost
CHARACTER_SET_CLIENT: utf8mb4
COLLATION_CONNECTION: utf8mb4_0900_ai_ci
DATABASE_COLLATION: utf8mb4_0900_ai_ci
#############此处省略n行数据#######################
*************************** 8. row ***************************
TRIGGER_CATALOG: def
TRIGGER_SCHEMA: goods
TRIGGER_NAME: after_delete
EVENT_MANIPULATION: DELETE
EVENT_OBJECT_CATALOG: def
EVENT_OBJECT_SCHEMA: goods
EVENT_OBJECT_TABLE: test_trigger
ACTION_ORDER: 1
ACTION_CONDITION: NULL
ACTION_STATEMENT: BEGIN
INSERT INTO test_trigger_log
(t_log)
VALUES
('after_delete')
;
END
ACTION_ORIENTATION: ROW
ACTION_TIMING: AFTER
ACTION_REFERENCE_OLD_TABLE: NULL
ACTION_REFERENCE_NEW_TABLE: NULL
ACTION_REFERENCE_OLD_ROW: OLD
ACTION_REFERENCE_NEW_ROW: NEW
CREATED: 2019-12-26 23:35:19.34
SQL_MODE: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_
FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
DEFINER: root@localhost
CHARACTER_SET_CLIENT: utf8mb4
COLLATION_CONNECTION: utf8mb4_general_ci
DATABASE_COLLATION: utf8mb4_0900_ai_ci
8 rows in set (0.00 sec)
17.3 删除触发器
当在数据库中确认某个触发器不再使用时,就可以将不再使用的触发器删除,在MySQL中,使用DROP TRIGGER语句删除触发器。
17.3.1 语法格式
删除触发器的语法格式如下:
DROP TRIGGER [IF EXISTS] [schema_name.]trigger_name
语法格式说明如下:
·DROP TRIGGER:删除触发器的SQL关键字。
·schema_name:触发器所在的数据库名称,可以省略。当省略时,会删除MySQL命令行所在的数据库下的触发器。
·trigger_name:触发器的名称。
17.3.2 删除触发器示例
例如,删除名称为after_delete的触发器。
mysql> DROP TRIGGER after_delete;
Query OK, 0 rows affected (0.11 sec)
SQL语句执行成功,查看alter_delete触发器的信息。
mysql> SHOW CREATE TRIGGER after_delete \G
ERROR 1360 (HY000): Trigger does not exist
结果显示,MySQL报错,不存在alter_delete触发器,说明alter_delete触发器已经被成功删除。
- 点赞
- 收藏
- 关注作者
评论(0)