引言
当使用关系型数据库和结构化查询语言(SQL)时,对数据的大多数操作都是显式执行查询的结果,例如SELECT
、INSERT
或UPDATE
。
然而,SQL数据库也可以被指令在特定事件发生时通过触发器自动执行预定义的操作。例如,您可以使用触发器来保存所有DELETE
语句的审计跟踪日志,或者在每次更新或添加到表中时自动更新聚合的统计摘要。
在本教程中,您将使用不同的SQL触发器来自动执行插入、更新或删除行的操作。
前期准备
遵循这个指南,你将需要一个计算机运行一个基于sql的关系数据库管理系统(RDBMS)。本指南中的说明和示例使用以下环境进行了验证:
-基本熟悉执行SELECT
、INSERT
、UPDATE
和DELETE
查询来操作数据库中的数据,如如何在SQL中从表中选择行,如何在SQL中插入数据,如何在SQL中更新数据,以及如何在SQL指南中删除数据所述。
-基本熟悉使用嵌套查询,如在SQL指南中如何使用嵌套查询中所述。
-基本熟悉使用聚集数学函数,如在SQL指南中如何使用数学表达式和聚集函数所述。
注意:许多RDBMS使用它们自己的SQL实现。虽然触发提到作为一个SQL标准的一部分,标准不严格执行他们的语法或实现它们的方法。因此,它们的实现在不同的数据库中是不同的。本教程中概述的命令使用MySQL数据库的语法,可能无法在其他数据库引擎上工作。
你还需要一个数据库,其中一些表加载了示例数据,这样你就可以练习使用函数。我们鼓励您通过以下连接到示例数据库MySQL和建立一个连接到MySQL服务器上部分细节,创建测试数据库在本指南中使用的例子。
连接到MySQL并设置一个示例数据库
如果SQL数据库系统运行在远程服务器上,请从本地设备SSH到服务器:
ssh sammy@your_server_ip
然后打开MySQL服务器提示符,将sammy
替换为你的MySQL用户账户的名称:
mysql -u sammy -p
创建一个名为collectibles
的数据库:
CREATE DATABASE collectibles;
如果数据库成功创建,您将收到这样的输出:
OutputQuery OK, 1 row affected (0.01 sec)
要选择collectibles
数据库,运行以下USE
语句:
USE collectibles;
OutputDatabase changed
选择数据库后,您可以在其中创建示例表。collectibles
表将包含数据库中关于收藏品的简化数据。它将保存以下列:
name
:这一列保存了每个收藏品的名称,使用varchar
数据类型表示,最多不超过50
个字符。value
:这一列使用decimal
数据类型存储收藏品的市值,小数点前的最大值为5
,小数点后的最大值为2
。
使用下面的命令创建示例表:
CREATE TABLE collectibles (name varchar(50),value decimal(5, 2)
);
如果输出结果如下所示,说明表已经创建:
OutputQuery OK, 0 rows affected (0.00 sec)
下一个表名为collectibles_stats
,用于记录集合中所有收藏品的累计价值。它将保存一行数据,包含以下列:
count
:这一列保存了拥有的收藏品的数量,使用int
数据类型表示。value
:这一列使用decimal
数据类型存储所有收藏品的累积值,小数点前最多为5
,小数点后最多为2
。
使用下面的命令创建示例表:
CREATE TABLE collectibles_stats (count int,value decimal(5, 2)
);
如果输出结果如下所示,说明表已经创建:
OutputQuery OK, 0 rows affected (0.00 sec)
第三张也是最后一张表叫做collectibles_archive
,它将记录所有从集合中删除的收藏品,以确保它们永远不会消失。它将保存类似于collectibles
表的数据,只是增加了删除日期。它使用以下列:
name
:这一列保存了每个被移除的收藏品的名称,使用varchar
数据类型表示,最多不超过50
个字符。value
:这一列使用decimal
数据类型存储收藏品删除时的市值,小数点前的值最多为5
,小数点后的值最多为2
。removed_on
:这一列存储了使用默认值为NOW()
的timestamp
数据类型删除每个存档集合的日期和时间,即每当有新行插入该表时的当前日期。
使用下面的命令创建示例表:
CREATE TABLE collectibles_archive (name varchar(50),value decimal(5, 2),removed_on timestamp DEFAULT CURRENT_TIMESTAMP
);
如果输出结果如下所示,说明表已经创建:
OutputQuery OK, 0 rows affected (0.00 sec)
接下来,通过运行以下INSERT INTO
操作,设置collectibles_stats
表:
INSERT INTO collectibles_stats SELECT COUNT(name), SUM(value) FROM collectibles;
INSERT INTO
操作将向collectibles_stats
添加一行使用聚合函数计算的值,对collectibles
表中的所有行进行计数,并使用value
列和SUM
函数对所有收藏品的价值求和。下面的输出表明已经添加了这一行:
OutputQuery OK, 1 row affected (0.002 sec)
Records: 1 Duplicates: 0 Warnings: 0
你可以通过在表上执行SELECT
语句来验证:
SELECT * FROM collectibles_stats;
由于数据库中还没有可收集的物品,所以初始的物品数量是0
,累积的值是NULL
:
Output+-------+-------+
| count | value |
+-------+-------+
| 0 | NULL |
+-------+-------+
1 row in set (0.000 sec)
有了这些,你就可以按照本指南的其余部分开始在MySQL中使用触发器了。
了解触发器
触发器语句定义了一个特定的表,数据库会自动执行每次该表中的指定的事件发生。触发器可以用来保证每次在表上执行特定语句时,某些操作都会一致地执行,而不需要数据库用户记住手动执行这些操作。
与表关联的每个触发器都用一个用户定义的名称和一对条件来标识,这些条件指示数据库引擎何时执行触发器。这些可以分为两个单独的类别:
- 数据库事件:当
INSERT
、UPDATE
或DELETE
语句在表上运行时,可以执行触发器。 - 事件时间:此外,触发器可以在相关语句的
BEFORE11
或AFTER
执行。
将两个条件组组合起来,总共产生6个单独的触发可能性,每次满足联合条件时自动执行这些触发可能性。在满足条件的语句执行之前发生的触发器是AFTER INSERT
、AFTER UPDATE
和AFTER DELETE
。它们可用于在数据插入或更新到表中之前操作和验证数据,或用于保存已删除行的详细信息以进行审计或存档。
在满足条件的语句执行之后发生的触发器是INSERT
之后、UPDATE
之后和DELETE
之后。这些可用于根据语句执行后数据库的最终状态更新单独表中的汇总值。
为了执行验证和操作输入数据或对删除的行进行归档等操作,数据库允许从触发器中访问数据值。对于INSERT
触发器,只有新插入的数据可以使用。对于UPDATE
触发器,原始数据和更新后的数据都可以访问。最后,使用DELETE
触发器,只有原始行数据可以使用(因为没有新数据可引用)。
触发器主体中使用的数据暴露在数据库中当前数据的OLD
记录下,以及查询将保存的数据的NEW
记录下。你可以使用OLD.column_name
和NEW.column_name
的语法来引用各个列。
下面的例子展示了用于创建新触发器的SQL语句的一般语法:
CREATE TRIGGER trigger_name trigger_condition
ON table_name
FOR EACH ROW
trigger_actions;
让我们把语法分解成更小的部分:
CREATE TRIGGER
是用于在数据库中创建新触发器的SQL语句的名称。trigger_name
是触发器的用户定义名称,用于描述其角色,类似于使用表名和列名来描述其含义。ON table_name
告诉数据库,触发器应该监控发生在table_name
表上的事件。trigger_condition
是定义何时运行触发器的六种可能选项之一,例如,BEFORE INSERT
。FOR EACH ROW
告诉数据库,应该为触发事件影响的每一行运行触发器。有些数据库支持除“FOR EACH ROW”之外的其他执行模式;然而,对于MySQL来说,为触发执行的语句影响的每一行运行触发器主体中的语句是唯一的选择。trigger_actions
是触发器的主体,定义了当触发器执行时会发生什么。它通常是一条有效的SQL语句。可以在触发器体中包含多条语句,使用BEGIN
和END
关键字将语句列表包含在一个块中来执行复杂的数据操作。然而,这超出了本教程的范围。查看触发器的官方文档以了解有关定义触发器的语法的更多信息。
在下一节中,我们将创建在INSERT
和UPDATE
操作之前操作数据的触发器。
使用BEFORE INSERT
和BEFORE UPDATE
触发器操作数据
在本节中,你将使用触发器在INSERT
和UPDATE
语句执行之前操作数据。
在这个例子中,你将使用触发器来确保数据库中的所有收藏品名称都使用大写,以保持一致性。如果不使用触发器,你将不得不记住为每个INSERT
和UPDATE
语句使用大写的集合名称。如果你忘记了,数据库将按原样保存数据,这可能会导致数据集中出现错误。
你将从插入一个名为太空船模型
的示例可收集物品开始,价值12.50
。项目名称将以小写形式书写,以说明问题。执行下面的语句:
INSERT INTO collectibles VALUES ('spaceship model', 12.50);
下面的消息确认添加了该项目:
OutputQuery OK, 1 row affected (0.009 sec)
你可以通过执行SELECT
查询来验证该行是否被插入:
SELECT * FROM collectibles;
Output+-----------------+-------+
| name | value |
+-----------------+-------+
| spaceship model | 12.50 |
+-----------------+-------+
1 row in set (0.000 sec)
这个收藏品被原样保存,只是名字的拼写只有小写字母。
为了确保所有未来的收藏品都是大写的,你需要创建一个BEFORE INSERT
触发器。使用触发器执行之前触发语句允许您运行操作的数据将被传递到数据库之前发生。
Run the following statement:
CREATE TRIGGER uppercase_before_insert BEFORE INSERT
ON collectibles
FOR EACH ROW
SET NEW.name = UPPER(NEW.name);
该命令创建了一个名为uppercase_before_insert
的触发器,它将在名为collectibles
的表上的所有INSERT
语句的BEFORE
执行。
触发器SET NEW.name = UPPER(NEW.name)
中的语句将对每一行插入执行。SET
SQL命令将右边的值赋给左边。在这种情况下,NEW.name
代表插入语句将保存的name
列的值。通过对集合名称应用UPPER
函数并将其赋值给列值,你正在转换将保存在数据库中的值的字母大小写。
注意:当运行CREATE TRIGGER
命令时,您可能会遇到类似ERROR 1419 (HY000): You do not have the SUPER privilege, and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)
的错误消息。
从MySQL 8开始,MySQL数据库引擎默认启用二进制日志记录,除非本地安装配置覆盖它。二进制日志以描述修改的已保存事件的形式跟踪所有修改数据库内容的SQL语句。这些日志用于数据库复制,以保持数据库副本的同步和在时间点数据恢复期间。
启用二进制日志记录后,MySQL不允许创建触发器和存储过程,作为预防措施,以保证复制环境中的数据安全和完整性。了解触发器和存储过程可以影响复制本指南的范围。
但是,在本地环境中,出于学习目的,您可以安全地覆盖MySQL防止创建触发器的方式。这个设置不会被持久化,重启MySQL服务器时就会恢复到原来的值。
要覆盖二进制日志的默认设置,请以root身份登录MySQL并执行以下命令:
SET GLOBAL log_bin_trust_function_creators = 1;
log_bin_trust_function_creators
设置控制是否可以信任创建触发器和存储函数的用户不会创建导致不安全事件被写入二进制日志的触发器。默认情况下,该设置的值为0
,只允许超级用户在启用二进制日志记录的环境中创建触发器。通过将值更改为1
,任何发出CREATE TRIGGER
语句的用户都会被信任,从而理解其中的含义。
更新设置后,以root身份注销,以用户身份重新登录,并重新运行CREATE TRIGGER
语句。
要了解更多关于MySQL中的二进制日志和复制以及它与触发器之间的关系,我们建议您参考MySQL官方文档:二进制日志和存储程序二进制日志。您还可以查看我们的教程,如何在MySQL中设置复制。
在具有复制功能的生产环境中使用触发器之前,或有严格的时间点恢复要求之前,请确保已经权衡了触发器对二进制日志一致性的影响。
注意:取决于你的MySQL用户权限,在执行CREATE TRIGGER
命令时可能会收到一个错误:ERROR 1142 (42000): TRIGGER command denied to user 'user'@'host' for table 'collectibles'
。要给你的用户授予TRIGGER
权限,以root身份登录MySQL并执行以下命令,根据需要替换MySQL用户名和主机:
GRANT TRIGGER on *.* TO 'sammy'@'localhost';
FLUSH PRIVILEGES;
更新用户权限后,以root身份注销,以用户身份重新登录,并重新运行CREATE TRIGGER
语句。
MySQL将打印以下消息,以确认触发器已成功创建:
OutputQuery OK, 1 row affected (0.009 sec)
现在尝试插入一个新的收藏品,同样使用小写参数给INSERT
查询:
INSERT INTO collectibles VALUES ('aircraft model', 10.00);
再一次检查collectibles
表中的结果行:
SELECT * FROM collectibles;
Output+-----------------+-------+
| name | value |
+-----------------+-------+
| spaceship model | 12.50 |
| AIRCRAFT MODEL | 10.00 |
+-----------------+-------+
2 rows in set (0.000 sec)
然而,这一次,新的条目显示的是AIRCRAFT MODEL
,所有字母都是大写——与你试图插入的条目不同。触发器在后台运行,并在行保存到数据库之前转换字母大小写。
所有新行现在都由触发器保护,以确保名称将以大写形式保存。然而,仍然可以使用UPDATE
语句来保存不受限制的数据。为了保证UPDATE
语句具有相同的效果,创建另一个触发器:
CREATE TRIGGER uppercase_before_update BEFORE UPDATE
ON collectibles
FOR EACH ROW
SET NEW.name = UPPER(NEW.name);
两个触发器之间的区别在于触发器的条件。这一次,它是BEFORE UPDATE
,意味着每当在表上发出UPDATE
语句时,触发器将执行——除了前一个触发器覆盖的新行之外,每次更新都会影响现有行。
MySQL会输出一个确认,已经成功地创建了触发器:
OutputQuery OK, 0 row affected (0.009 sec)
为了验证新触发器的行为,尝试更新spaceship model
的价格:
UPDATE collectibles SET value = 15.00 WHERE name = 'spaceship model';
WHERE
子句过滤要更新的行,SET
子句将值更改为15.00
。
你会收到以下输出,确认这条语句只修改了一行:
OutputQuery OK, 1 row affected (0.002 sec)
Rows matched: 1 Changed: 1 Warnings: 0
查看collectibles
表中的结果行:
SELECT * FROM collectibles;
Output+-----------------+-------+
| name | value |
+-----------------+-------+
| SPACESHIP MODEL | 15.00 |
| AIRCRAFT MODEL | 10.00 |
+-----------------+-------+
2 rows in set (0.000 sec)
现在,除了价格被执行的语句更新到15.00
之外,名称现在是SPACESHIP MODEL
。当你运行UPDATE
语句时,触发器被执行,影响了更新行的值。name
列在保存之前被转换为大写。
在本节中,我们创建了两个在INSERT
和UPDATE
查询之前工作的触发器,它们在将数据保存到数据库之前使数据符合规范。在下一节中,您将使用BEFORE DELETE
触发器将删除的行复制到单独的表中进行归档。
使用BEFORE DELETE
触发器在删除行之前执行操作
即使你不再拥有某项,也可能希望在另一张表中留下一条关于删除的记录。在本教程开始时,你创建了第二个名为collectibles_archive
的表,用于记录从集合中删除的所有收藏品。在本节中,你将使用触发器将删除的条目归档,该触发器将在DELETE
语句之前执行。
执行以下语句检查归档表是否为空:
SELECT * FROM collectibles_archive;
以下输出将打印到屏幕上,确认collectibles_archive
表为空:
OutputEmpty set (0.000 sec)
现在,如果你对collectibles
表执行DELETE
查询,表中的任何行都可能被删除而不会被跟踪。
为了解决这个问题,你需要创建一个触发器,它会在collectibles
表上的所有DELETE
查询之前执行。此触发器的目的是在删除发生之前将已删除对象的副本保存到归档表中。
运行下面的命令:
CREATE TRIGGER archive_before_delete BEFORE DELETE
ON collectibles
FOR EACH ROW
INSERT INTO collectibles_archive (name, value) VALUES (OLD.name, OLD.value);
触发器名为archive_before_delete
,在collectibles
表的BEFORE
中执行任何DELETE
查询。对于将要被删除的每一行,INSERT
语句将被执行。反过来,INSERT
语句将从OLD
记录中获取的数据值插入到collectibles_archive
表中:OLD.name
变成了name
列,OLD.value
变成了value
列。
数据库将确认触发器的创建:
OutputQuery OK, 0 row affected (0.009 sec)
有了触发器之后,试着从主要的收藏品表中删除收藏品:
DELETE FROM collectibles WHERE name = 'SPACESHIP MODEL';
OutputQuery OK, 1 row affected (0.004 sec)
现在,列出所有收藏品:
SELECT * FROM collectibles;
Output+----------------+-------+
| name | value |
+----------------+-------+
| AIRCRAFT MODEL | 10.00 |
+----------------+-------+
1 row in set (0.000 sec)
现在只剩下AIRCRAFT MODEL
; SPACESHIP MODEL
已被删除,不再是在桌上。但是,使用之前创建的触发器,此删除应该注册在collectibles_archive
表中。我们来检查一下。
执行另一个查询:
SELECT * FROM collectibles_archive;
Output+-----------------+-------+---------------------+
| name | value | removed_on |
+-----------------+-------+---------------------+
| SPACESHIP MODEL | 15.00 | 2022-11-20 11:32:01 |
+-----------------+-------+---------------------+
1 row in set (0.000 sec)
该删除由触发器自动记录在该表中。name
和value
列已经填充了被删除行的数据。第三列,removed_on
,没有通过定义的触发器显式设置,所以它使用创建表期间决定的默认值:任何新行创建的日期。因此,在触发器的帮助下添加的每个条目都会标注删除日期。
有了这个触发器,你现在可以确定所有的DELETE
查询都会在collectibles_archive
中产生一个日志条目,留下关于之前拥有的收藏品的信息。
在下一节中,您将使用在触发语句之后执行的触发器,使用基于所有收集的聚合值更新汇总表。
使用AFTER INSERT
、AFTER UPDATE
和AFTER DELETE
触发器在数据操作之后执行操作
在前面两节中,我们使用了在main语句之前执行的触发器,在更新数据库之前执行基于原始数据的操作。在本节中,您将使用始终最新的计数和所有集合的累积值来更新汇总表,使用在预期语句之后执行的触发器。这样,您将确保汇总表数据考虑到数据库的当前状态。
首先检查collectibles_stats
表:
SELECT * FROM collectibles_stats;
由于您还没有向此表添加信息,因此拥有的收藏品数量为0
,因此累计值为NULL
:
Output+-------+-------+
| count | value |
+-------+-------+
| 0 | NULL |
+-------+-------+
1 row in set (0.000 sec)
因为这张表没有触发器,所以之前发布的插入和更新收藏品的查询不会影响这张表。
我们的目标是在collectibles_stats
表的单行中设置值,以显示有关收藏品数量和总价值的最新信息。你希望确保表的内容在每次INSERT
、UPDATE
或DELETE
操作后都被更新。
您可以通过创建三个单独的触发器来实现这一点,它们都在相应的查询之后执行。首先,创建AFTER INSERT
触发器:
CREATE TRIGGER stats_after_insert AFTER INSERT
ON collectibles
FOR EACH ROW
UPDATE collectibles_stats
SET count = (SELECT COUNT(name) FROM collectibles
), value = (SELECT SUM(value) FROM collectibles
);
触发器名为stats_after_insert
,它将在INSERT
查询collectibles
表的之后
执行,并在触发器体中运行UPDATE
语句。UPDATE
查询会影响collectibles_stats
,并将count
和value
列设置为嵌套查询返回的值:
SELECT COUNT(name) FROM collectibles
会得到收藏品的数量SELECT SUM(value) FROM collectibles
将获得所有收藏品的总价值
数据库将确认触发器的创建:
OutputQuery OK, 0 row affected (0.009 sec)
现在,尝试将之前删除的spaceship model
重新插入到collections
表中,以检查汇总表是否会正确更新:
INSERT INTO collectibles VALUES ('spaceship model', 15.00);
OutputQuery OK, 1 row affected (0.009 sec)
你可以通过运行以下命令列出所有拥有的收藏品:
SELECT * FROM collectibles;
Output+-----------------+-------+
| name | value |
+-----------------+-------+
| AIRCRAFT MODEL | 10.00 |
| SPACESHIP MODEL | 15.00 |
+-----------------+-------+
2 rows in set (0.000 sec)
游戏中有两件总价值为“25.00”的收藏品。检查汇总表后新插入的项,执行以下查询:
SELECT * FROM collectibles_stats;
这一次,汇总表将列出所有拥有的收藏品的数量为2
,累计值为25.00
,这与前一个输出相匹配:
Output+-------+-------+
| count | value |
+-------+-------+
| 2 | 25.00 |
+-------+-------+
1 row in set (0.000 sec)
stats_after_insert
触发器在INSERT
查询之后运行,并用集合的当前数据(count
和value
)更新collectibles_stats
表。统计信息收集的是整个集合的内容,而不仅仅是最后一次插入。因为这个集合现在包含两个项目(飞机和飞船模型),所以汇总表列出了两个项目及其求和值。此时,向collectibles
表中添加任何新的可收集物品都会用正确的值更新汇总表。
然而,更新现有的项目或删除收藏品不会影响总结。为了填补这个空白,我们将创建两个额外的触发器,执行相同的操作,但由不同的事件触发:
CREATE TRIGGER stats_after_update AFTER UPDATE
ON collectibles
FOR EACH ROW
UPDATE collectibles_stats
SET count = (SELECT COUNT(name) FROM collectibles
), value = (SELECT SUM(value) FROM collectibles
);CREATE TRIGGER stats_after_delete AFTER DELETE
ON collectibles
FOR EACH ROW
UPDATE collectibles_stats
SET count = (SELECT COUNT(name) FROM collectibles
), value = (SELECT SUM(value) FROM collectibles
);
现在你已经创建了两个新的触发器:stats_after_update
和stats_after_delete
。当你在collectibles
表上执行UPDATE
或DELETE
语句时,这两个触发器都会在collectible_stats
表上运行。
成功创建这些触发器后,将打印以下输出:
OutputQuery OK, 0 row affected (0.009 sec)
现在,更新其中一件收藏品的价格:
UPDATE collectibles SET value = 25.00 WHERE name = 'AIRCRAFT MODEL';
WHERE
子句过滤要更新的行,SET
子句将值更改为25.00
。
输出确认了该语句只修改了一行:
OutputQuery OK, 1 row affected (0.002 sec)
Rows matched: 1 Changed: 1 Warnings: 0
同样,在更新后检查汇总表的内容:
SELECT * FROM collectibles_stats;
value
现在列出了40.00
,这是更新后的正确值:
Output+-------+-------+
| count | value |
+-------+-------+
| 2 | 40.00 |
+-------+-------+
1 row in set (0.000 sec)
最后一步是验证汇总表是否正确地反映了收藏品的删除。尝试用下面的语句删除飞机模型:
DELETE FROM collectibles WHERE name = 'AIRCRAFT MODEL';
OutputQuery OK, 1 row affected (0.004 sec)
现在,列出所有的收藏品:
SELECT * FROM collectibles;
Output+-----------------+-------+
| name | value |
+-----------------+-------+
| SPACESHIP MODEL | 15.00 |
+-----------------+-------+
1 row in set (0.000 sec)
现在只剩下SPACESHIP MODEL
了。接下来,检查汇总表中的值:
SELECT * FROM collectibles_stats;
Output+-------+-------+
| count | value |
+-------+-------+
| 1 | 15.00 |
+-------+-------+
1 row in set (0.000 sec)
count
列现在显示在主表中只有一个可收集的元素。总值为15.00
,与SPACESHIP MODEL
的值匹配。
这三个触发器在INSERT
、UPDATE
和DELETE
查询之后共同工作,以保持汇总表与完整的收藏品列表同步。
在下一节中,您将学习如何处理现有的数据库触发器。
列出和删除触发器
在前面几节中,我们创建了新的触发器。因为触发器是在数据库中定义的命名对象,就像表一样,你也可以列出它们并在需要时操作它们。
列出所有触发器、执行SHOW TRIGGERS
SQL语句:
SHOW TRIGGERS;
输出将包括所有触发器,包括它们的名称、触发事件的时间(BEFORE
或AFTER
语句执行),以及作为触发器主体的语句和触发器定义的其他详细信息:
Output, simplified for readability+-------------------------+--------+--------------+--------(...)+--------+(...)
| Trigger | Event | Table | Statement | Timing |(...)
+-------------------------+--------+--------------+--------(...)+--------+(...)
| uppercase_before_insert | INSERT | collectibles | SET (...)| BEFORE |(...)
| stats_after_insert | INSERT | collectibles | UPDATE (...)| AFTER |(...)
| uppercase_before_update | UPDATE | collectibles | SET (...)| BEFORE |(...)
| stats_after_update | UPDATE | collectibles | UPDATE (...)| AFTER |(...)
| archive_before_delete | DELETE | collectibles | INSERT (...)| BEFORE |(...)
| stats_after_delete | DELETE | collectibles | UPDATE (...)| AFTER |(...)
+-------------------------+--------+--------------+--------(...)+--------+(...)
6 rows in set (0.001 sec)
To delete existing triggers, you can use DROP TRIGGER
SQL statements. Perhaps you no longer want to enforce uppercase letters for collectible names, so the uppercase_before_insert
and uppercase_before_update
are no longer needed. Execute the following commands to remove these two triggers:
删除现有的触发器,可以使用DROP TRIGGER
SQL语句。也许你不再想执行收藏的大写字母的名字,所以“uppercase_before_insert”和“uppercase_before_update”不再需要。执行以下命令删除这两个触发器:
DROP TRIGGER uppercase_before_insert;
DROP TRIGGER uppercase_before_update;
OutputQuery OK, 0 rows affected (0.004 sec)
现在,有了这两个触发器,让我们添加一个新的小写收藏品:
INSERT INTO collectibles VALUES ('ship model', 10.00);
OutputQuery OK, 1 row affected (0.009 sec)
你可以通过执行SELECT
查询来验证该行是否被插入:
SELECT * FROM collectibles;
Output+-----------------+-------+
| name | value |
+-----------------+-------+
| SPACESHIP MODEL | 15.00 |
| ship model | 10.00 |
+-----------------+-------+
2 rows in set (0.000 sec)
新添加的收藏品是小写字母。由于名称与原始输出相比没有改变,您已经确认以前转换字母大小写的触发器不再使用。
现在你知道了如何按名称列出和删除触发器。
总结
通过本指南,你了解了什么是SQL触发器,以及如何在MySQL中使用它们在INSERT
和UPDATE
查询之前操作数据。你学习了如何使用BEFORE DELETE
触发器将删除的行归档到单独的表中,以及如何使用AFTER
语句触发器来保持汇总始终是最新的。
你可以使用函数将一些数据操作和验证交给数据库引擎,以确保数据完整性或对日常数据库用户隐藏一些数据库行为。本教程只介绍了为此目的使用触发器的基础知识。你可以构建由多个语句组成的复杂触发器,并使用条件逻辑更细粒度地执行操作。要了解更多信息,请参阅MySQL关于触发器的文档。