什么是数据库触发器
什么是数据库触发器?
目录
什么是数据库触发器?
数据库触发器是在数据库中发生特定操作时运行的特殊 存储过程 。大多数触发器定义为在对表的数据进行更改时运行。触发器可以定义为替代或在
DML
(数据操纵语言)
如
INSERT, UPDATE, and DELETE
之后来运行。
触发器可帮助数据库设计人员确保完成某些操作(如维护审计文件),而不管哪个程序或用户对数据进行了更改。
程序被称为触发器,因为事件(例如向表中添加记录)会触发它们的执行。
触发器及其实现特定于数据库供应商。在本文中,我们将重点介绍
Microsoft SQL
服务器
;
但是,
Oracle
和
MySQL
中的概念相同或相似。
注意:本课程的所有示例均基于
Microsoft SQL Server Management Studio
和
AdventureWorks2012
数据库。
事件
触发器可以在
DML
操作之后发生,也可以不发生。触发器与数据库
DML
操作
INSERT
,
UPDATE
和
DELETE
相关联。触发器定义为在特定表上执行这些操作时运行。
AFTER 触发器
一旦
DML
操作(例如
INSERT
)完成,就会执行
AFTER
触发器。以下是
AFTER
触发器的一些关键特性:
在
DML
操作之后运行触发器之后,例如
INSERT
语句和任何随后的参考级联操作和约束检查已运行。
您无法使用
AFTER
触发器取消数据库操作。这是因为该行动已经完成。
可以在表上定义每个动作一个或多个
AFTER
触发器,但为了简单起见,我建议仅定义一个。
您无法在视图上定义
AFTER
触发器。
INSTEAD OF 触发器
顾名思义,
INSTEAD OF
触发器代替导致它们触发的
DML
动作。使用
INSTEAD OF
触发器时要考虑的事项包括:
INSTEAD OF
触发器会覆盖触发操作。如果定义一个
INSTEAD OF
触发器在
INSERT
语句上执行,那么一旦
INSERT
语句尝试运行,控制就会立即传递给
INSTEAD OF
触发器。
最多可以为表的每个操作定义一个
INSTEAD OF
触发器。这是有道理的,就好像你必须为插入一个
“INSTEAD OF”
触发器一样,哪一个应该运行?
特殊数据库对象
触发器使用两个特殊的数据库对象
INSERTED
和
DELETED
来访问受数据库操作影响的行。在触发器的范围内,
INSERTED
和
DELETE
对象具有与触发器表相同的列。
INSERTED
表包含所有新值
;
而
DELETED
表包含旧值。以下是表格的使用方法:
INSERT
——使用
INSERTED
表确定将哪些行添加到表中。
DELETE
——使用
DELETED
表查看从表中删除的行。
UPDATE
——使用
INSERTED
表检查新值或更新值,使用
DELETED
表查看更新前的值。
定义
为特定表和一个或多个事件定义触发器。在大多数数据库管理系统中,每个表只能定义一个触发器。
以下是
AdventureWorks2012
数据库的示例触发器。
您会注意到触发器的语法与存储过程的语法非常相似。事实上,触发器使用相同的语言来实现其逻辑,就像 存储过程一样 。在
MS SQL
中,这是
;
而在
Oracle
中则是
。
以下是触发器的一些重要部分:
CREATE
语句——它定义哪个表与触发器相关联。此外,此语句用于指定触发器何时执行(例如插入后)。
实际的程序。在该示例中,只要将一行或多行插入
WorkOrder
表,该程序就会运行。
特殊数据库对象——触发器使用特殊定义的数据库对象(如
INSERTED
或
DELETED
)来访问受数据库操作影响的记录。
在此示例中,触发器使用
INSERTED
对象来访问新创建的行。
INSERT
语句用于表示这些行并将它们添加到历史表中。
用于触发器
以下是触发器的一些常见用法:
复杂的审计
您可以使用触发器来跟踪对表所做的更改。在上面的示例中,对
WorkOrder
表所做的更改将记录在
TransactionHistory
表中。
通常在创建审计跟踪时,您将使用
AFTER
触发器。
您可能认为这是多余的,因为数据库日志中记录了许多更改,但日志用于数据库恢复,用户程序无法轻松访问。
TransactionHistory
表易于引用,可以合并到最终用户报告中。
执行业务规则
触发器可用于在执行
DML
操作之前检查所有数据。您可以使用
INSTEAD OF
触发器
“
拦截
”
挂起的
DML
操作,应用任何业务规则,并最终完成事务。
示例业务规则可以是客户状态定义为:
黄金——过去
12
个月的购买量超过
1,000,000
美元。
白银——在过去
12
个月内购买
500,000
美元至
1,000,000
美元。
青铜——所有其他购买水平。
可以定义
INSTEAD OF
触发器,以便在每次添加或修改客户记录时检查客户状态。状态检查将涉及创建所有客户购买的总和,并确保新状态与过去
12
个月的购买总和相对应。
派生列值
触发器可用于计算列值。例如,对于每个客户,您可能希望在客户记录上维护
TotalSales
列。当然,为了保持准确,每次销售时都必须更新。
这可以使用
Sales
表的
INSERT
,
UPDATE
和
DELETE
语句上的
AFTER
触发器来完成。
触发器很棘手!
一般来说,我的建议是避免使用触发器,除非绝对必要。
您应该避免使用触发器代替内置功能。例如,不是依靠触发器来强制执行引用完整性,而是最好使用
。
以下是我回避他们的一些原因:
他们可能很难排除故障。
触发器可以触发其他触发器。两个表
A
和
B
都有一个
AFTER UPDATE
触发器。如果表
A
上的
AFTER UPDATE
触发器更新表
B
,则更新表
A
会导致触发,然后
B
触发。
你必须确保不会造成触发风暴!你能想象表
B
由于某种原因更新了表
A
吗?现在你有一个循环参考
……
轰!
我尝试将尽可能多的逻辑移动到存储过程中,并让应用程序通过它们而不是直接的
SQL
语句来更改数据库。