SQL Server 中的触发器触发器是一个数据库对象,类似于存储过程,当数据库中发生事件时会自动执行。有不同类型的事件可以激活触发器,例如在表中插入或删除行、用户登录到数据库服务器实例、更新表列、创建、更改或删除表等。
例如,考虑一种情况,在 `Employee` 表中更新员工的工资。您可能希望在工资更新到新值之前,将以前的工资详细信息保存在单独的审计表中。您可以创建一个触发器,在 `Employee` 表的值更新时,自动将更新的员工数据插入到新的审计表中。
SQL Server 中有三种类型的触发器
DML 触发器在表的 INSERT、UPDATE 或 DELETE 事件发生时自动触发。DDL 触发器在数据库中发生 CREATE、ALTER 或 DROP 事件时自动调用。它响应服务器范围或数据库范围的事件而触发。登录触发器在用户会话建立时发生 LOGON 事件时调用。DML 触发器DML(数据操纵语言)触发器在对表执行 INSERT、UPDATE 或 DELETE 语句时自动调用。
使用 CREATE TRIGGER 语句在 SQL Server 中创建触发器。
语法:创建触发器 复制CREATE TRIGGER [schema_name.]trigger_name
ON { table_name | view_name }
{ FOR | AFTER | INSTEAD OF } {[INSERT],[UPDATE],[DELETE]}
[NOT FOR REPLICATION]
AS
{sql_statements}在上述语法中
`schema_name`(可选)是要创建新触发器的架构名称。`trigger_name` 是新触发器的名称。`ON { table_name | view_name }` 关键字指定将在其上创建触发器的表或视图名称。`AFTER` 子句指定将触发触发器的 INSERT、UPDATE 或 DELETE 事件。AFTER 子句指定触发器仅在 SQL Server 成功完成触发它的操作的执行后才触发。所有其他操作和约束都应在触发器触发之前成功执行。`INSTEAD OF` 子句用于跳过对表的 INSERT、UPDATE 或 DELETE 语句,并改为执行触发器中定义的其他语句。因此,实际的 INSERT、UPDATE 或 DELETE 语句根本不会发生。INSTEAD OF 子句不能用于 DDL 触发器。`[NOT FOR REPLICATION]` 子句用于指示 SQL Server 在复制代理修改表时不调用触发器。`sql_statements` 指定事件发生时要执行的操作。DML 触发器使用两个特殊的临时表,称为 inserted 表和 deleted 表。SQL Server 自动创建和管理这些表。SQL Server 使用这些表来查找数据修改前后表的状态,并根据该差异采取行动。
插入表删除表在 INSERT 或 UPDATE 事件期间保存要插入的新行。在 DELETE 或 UPDATE 事件期间保存受影响行的副本。DELETE 语句没有记录。INSERT 语句没有记录。让我们创建一个在 `Employee` 表上对 INSERT、UPDATE 和 DELETE 操作触发的触发器。为此,创建一个新表 `EmployeeLog` 以记录对 `Employee` 表执行的所有操作。
示例:创建日志表 复制CREATE TABLE EmpLog (
LogID int IDENTITY(1,1) NOT NULL,
EmpID int NOT NULL,
Operation nvarchar(10) NOT NULL,
UpdatedDate Datetime NOT NULL
)在上面的表中,`LogID` 是自动递增的序列号,`UpdatedDate` 是 `Employee` 表更新的日期。`Operation` 列存储对表进行的操作类型;可以是“INSERT”、“UPDATE”或“DELETE”。
FOR 触发器FOR 触发器可以在表或视图上定义。它仅在触发 SQL 语句中指定的所有操作都成功启动后才触发。在触发器触发之前,所有引用级联操作和约束检查也必须成功。
以下 FOR 触发器在 `Employee` 表的 INSERT 操作上触发。
示例:FOR 触发器 复制CREATE TRIGGER dbo.trgEmployeeInsert
ON dbo.Employee
FOR INSERT
AS
INSERT INTO dbo.EmpLog(EmpID, Operation, UpdatedDate)
SELECT EmployeeID ,'INSERT',GETDATE() FROM INSERTED; --virtual table INSERTED上面将在
执行 `Employee` 和 `EmpLog` 表上的 SELECT 语句以查看现有记录。
以下是 `EmpLog` 表。
现在,执行以下 INSERT 语句,它将触发 `trgEmployeeInsert` 触发器。
示例:插入数据 复制INSERT INTO Employee(FirstName
,LastName
,Phone
,HireDate
,ManagerID
,Salary
,DepartmentID)
VALUES('Manisha'
,'Dutt'
,'[email protected]'
,6799878453
,'11/07/2015'
,5
,50000
,20)上面将在 `Employee` 表中插入一个新行,如下所示。
`trgEmployeeInsert` 将被触发并在 `EmpLog` 表中插入一行,如下所示。
您可以看到,对于 `Employee` 表的每个 INSERT 语句,`EmpLog` 表中都会插入一个新行。
注意:如果 FOR 触发器因任何原因失败,则 INSERT 也会失败,并且不会插入任何行。
AFTER 触发器AFTER 触发器仅在指定的触发 SQL 语句成功完成后才触发。AFTER 触发器不能在视图上定义。
例如,以下触发器将在 `Employee` 表上的每个 UPDATE 语句之后触发。
示例:AFTER 触发器 复制CREATE TRIGGER dbo.trgEmployeeUpdate
ON dbo.Employee
AFTER UPDATE
AS
INSERT INTO dbo.EmpLog(EmpID, Operation, UpdatedDate)
SELECT EmployeeID,'UPDATE', GETDATE() FROM DELETED;要测试此触发器,请执行以下 UPDATE 语句。
示例:插入数据 复制UPDATE Employee
SET salary = 55000
WHERE EmployeeID = 2;现在,从 `EmpLog` 表中选择行。`trgEmployeeUpdate` 触发器应该已经在 `EmpLog` 表中插入了一个新行,如下所示。
INSTEAD OF 触发器INSTEAD OF 触发器允许您覆盖表或视图上的 INSERT、UPDATE 或 DELETE 操作。实际的 DML 操作根本不会发生。
INSTEAD OF DELETE 触发器代替表或视图上的实际删除事件执行。在下面的 Instead Of delete 触发器示例中,当对 Employee 表发出 delete 命令时,会在 `EmpLog` 表中创建一个新行,将操作存储为“Delete”,但该行不会被删除。
示例:INSTEAD OF 触发器 复制CREATE TRIGGER dbo.trgInsteadOfDelete
ON dbo.Employee
INSTEAD OF DELETE
AS
INSERT INTO dbo.EmpLog(EmpID, Operation, UpdatedDate)
SELECT EmployeeID,'DELETE', GETDATE() FROM DELETED;现在,执行以下 delete 语句来测试上面的触发器。
示例:INSTEAD OF 触发器 复制DELETE FROM Employee
WHERE EmployeeID = 16;上述语句将触发 `trgInsteadOfDelete` 触发器,该触发器将在 `EmpLog` 表中插入一个新行,而不是在 `Employee` 表中删除一个行。
INSTEAD OF DELETE 触发器对于批量删除也以相同的方式工作。当您运行删除多行的 SQL 语句时,这些行不会被删除,但会在 `EmpLog` 表中插入相同数量的行。
多个触发器在 SQL Server 中,可以在一个表上为相同的事件创建多个触发器。这些触发器没有定义的执行顺序。
可以使用存储过程 sp_settriggerorder 将触发器的顺序设置为 First 或 Last。一个表只能有一个 First 或 Last 触发器。在第一个定义的触发器和最后一个定义的触发器之间触发的所有触发器都没有任何保证的触发顺序。考虑一个有四个或更多触发器的场景。在第一个定义的触发器触发后,其他触发器没有定义的触发顺序,直到最后,最后一个定义的触发器才触发。
语法 复制sp_settriggerorder [ @triggername = ] 'triggername',
[ @order = ] 'value',
[ @stmttype = ] 'statement_type',
[ @namespace = { 'DATABASE' | 'SERVER' | NULL } ]参数
Triggername 是要排序的触发器名称@order = 触发器的顺序。First、Last 或 None@stmttype = 语句类型。INSERT、UPDATE、DELETE、LOGON 或 DDL 事件中列出的任何 TSQL 语句事件。@namespace 指定 DDL 触发器是在数据库上还是在服务器上创建的。假设您有多个触发器在 `Employee` 表上的更新语句上触发。以下示例指定触发器 `trgEmployeeUpdate` 是在 `Employee` 表上发生 UPDATE 操作后第一个触发的触发器。
示例:设置触发器顺序 复制sp_settriggerorder @triggername= 'dbo.trgEmployeeUpdate',
@order='First',
@stmttype = 'UPDATE';使用 SSMS 创建 DML 触发器步骤 1:打开 SSMS 并登录到数据库服务器。在对象资源管理器中,展开数据库实例并选择要创建触发器的数据库。
步骤 2:展开要创建触发器的表。右键单击“触发器”文件夹并选择“新建触发器”。新触发器的 CREATE TRIGGER 语法将在查询编辑器中打开。
步骤 3:在“查询”菜单中,单击“为模板参数指定值”。
在对话框中,指定触发器名称、创建日期、架构名称、触发器作者,并填写其他参数。单击“确定”。
步骤 4:在查询编辑器中,在注释部分输入触发器的 SQL 语句 – 在此处插入触发器语句。
步骤 5:您可以单击“查询”菜单下的“分析”来验证语法。
步骤 6:单击“执行”以创建触发器。
步骤 7:刷新表。新触发器将创建在表的“触发器”文件夹下。
这样,您就可以在 SSMS 中创建触发器。