什么是数据库触发器?

目录

什么是数据库触发器?

事件

AFTER触发器

INSTEAD OF触发器

特殊数据库对象

定义

用于触发器

复杂的审计

执行业务规则

派生列值

触发器很棘手!


什么是数据库触发器?

数据库触发器是在数据库中发生特定操作时运行的特殊存储过程。大多数触发器定义为在对表的数据进行更改时运行。触发器可以定义为替代或在DML(数据操纵语言)-INSERT, UPDATE, and DELETE-之后来运行。

触发器可帮助数据库设计人员确保完成某些操作(如维护审计文件),而不管哪个程序或用户对数据进行了更改。

程序被称为触发器,因为事件(例如向表中添加记录)会触发它们的执行。

触发器及其实现特定于数据库供应商。在本文中,我们将重点介绍Microsoft SQL服务器;但是,OracleMySQL中的概念相同或相似。

注意:本课程的所有示例均基于Microsoft SQL Server Management StudioAdventureWorks2012数据库。

事件

触发器可以在DML操作之后发生,也可以不发生。触发器与数据库DML操作INSERTUPDATEDELETE相关联。触发器定义为在特定表上执行这些操作时运行。

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”触发器一样,哪一个应该运行?

特殊数据库对象

触发器使用两个特殊的数据库对象INSERTEDDELETED来访问受数据库操作影响的行。在触发器的范围内,INSERTEDDELETE对象具有与触发器表相同的列。

INSERTED表包含所有新值;DELETED表包含旧值。以下是表格的使用方法:

  • INSERT——使用INSERTED表确定将哪些行添加到表中。
  • DELETE——使用DELETED表查看从表中删除的行。
  • UPDATE——使用INSERTED表检查新值或更新值,使用DELETED表查看更新前的值。

定义

为特定表和一个或多个事件定义触发器。在大多数数据库管理系统中,每个表只能定义一个触发器。

以下是AdventureWorks2012数据库的示例触发器。

什么是数据库触发器?_第1张图片

您会注意到触发器的语法与存储过程的语法非常相似。事实上,触发器使用相同的语言来实现其逻辑,就像存储过程一样。在MS SQL中,这是T-SQL;而在Oracle中则是PL/SQL

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

  1. CREATE语句——它定义哪个表与触发器相关联。此外,此语句用于指定触发器何时执行(例如插入后)。
  2. 实际的程序。在该示例中,只要将一行或多行插入WorkOrder表,该程序就会运行。
  3. 特殊数据库对象——触发器使用特殊定义的数据库对象(如INSERTEDDELETED)来访问受数据库操作影响的记录。
  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表的INSERTUPDATEDELETE语句上的AFTER触发器来完成。

触发器很棘手!

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

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

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

  1. 他们可能很难排除故障。
  2. 触发器可以触发其他触发器。两个表AB都有一个AFTER UPDATE触发器。如果表A上的AFTER UPDATE触发器更新表B,则更新表A会导致触发,然后B触发。
  3. 你必须确保不会造成触发风暴!你能想象表B由于某种原因更新了表A吗?现在你有一个循环参考......轰!
  4. 我尝试将尽可能多的逻辑移动到存储过程中,并让应用程序通过它们而不是直接的SQL语句来更改数据库。

你可能感兴趣的:(数据库,触发器)