目录

什么是数据库触发器

什么是数据库触发器?

目录


什么是数据库触发器?

数据库触发器是在数据库中发生特定操作时运行的特殊 存储过程 。大多数触发器定义为在对表的数据进行更改时运行。触发器可以定义为替代或在

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

数据库的示例触发器。

https://i-blog.csdnimg.cn/blog_migrate/ba16c64673c07f5ef105ac64ddf76921.png

您会注意到触发器的语法与存储过程的语法非常相似。事实上,触发器使用相同的语言来实现其逻辑,就像 存储过程一样 。在

MS SQL

中,这是

;

而在

Oracle

中则是

以下是触发器的一些重要部分:

  1. CREATE

    语句——它定义哪个表与触发器相关联。此外,此语句用于指定触发器何时执行(例如插入后)。

  2. 实际的程序。在该示例中,只要将一行或多行插入

    WorkOrder

    表,该程序就会运行。

  3. 特殊数据库对象——触发器使用特殊定义的数据库对象(如

    INSERTED

    DELETED

    )来访问受数据库操作影响的记录。

  4. 在此示例中,触发器使用

    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

触发器来完成。

触发器很棘手!

一般来说,我的建议是避免使用触发器,除非绝对必要。

您应该避免使用触发器代替内置功能。例如,不是依靠触发器来强制执行引用完整性,而是最好使用

以下是我回避他们的一些原因:

  1. 他们可能很难排除故障。

  2. 触发器可以触发其他触发器。两个表

    A

    B

    都有一个

    AFTER UPDATE

    触发器。如果表

    A

    上的

    AFTER UPDATE

    触发器更新表

    B

    ,则更新表

    A

    会导致触发,然后

    B

    触发。

  3. 你必须确保不会造成触发风暴!你能想象表

    B

    由于某种原因更新了表

    A

    吗?现在你有一个循环参考

    ……

    轰!

  4. 我尝试将尽可能多的逻辑移动到存储过程中,并让应用程序通过它们而不是直接的

    SQL

    语句来更改数据库。