一、什么是触发器(Trigger)?
触发器本质是一种特殊的存储过程,但其最大特点是——无需任何人手动调用。只要对表执行特定操作,它就会自动触发并执行相应逻辑。

哪些操作可以激活触发器?最常见的有三种:
INSERT(插入数据)UPDATE(更新数据)DELETE(删除数据)
简单理解就是:
当表中数据发生变化时,数据库自动执行的一段“监听程序”。
触发器的典型用途
数据审计——记录谁在何时修改了哪些数据,改动痕迹清晰可查
数据校验——拦截不符合规范的操作,例如禁止工资出现负数
自动维护关联数据——下单时自动扣减库存,省时高效
业务规则约束——例如库存不能为负,用触发器实现非常直接
二、触发器的分类
SQL Server 中的触发器主要分为两大类:
1. DML 触发器(针对表)
作用对象:INSERT / UPDATE / DELETE 这三种操作。
它又分为两种形态:
(1)AFTER 触发器(操作之后触发)
在操作执行完成后触发器才被执行。举个简单的例子:
CREATE TRIGGER trg_AfterInsert
ON Student
AFTER INSERT
AS
BEGIN
PRINT '插入数据成功'
END(2)INSTEAD OF 触发器(替代执行)
不执行原始操作,而是由触发器代劳。常用于视图,或需要彻底禁止某种操作的场景。
CREATE TRIGGER trg_InsteadDelete
ON Student
INSTEAD OF DELETE
AS
BEGIN
PRINT '禁止删除学生记录'
END2. DDL 触发器(针对数据库级操作)
监听的不再是数据变化,而是结构变化——比如建表、删表、改表、创建登录等。
CREATE TRIGGER trg_DDL
ON DATABASE
FOR DROP_TABLE
AS
BEGIN
PRINT '禁止删除表结构'
END三、Inserted 与 Deleted 表(核心概念)
在 DML 触发器中,SQL Server 为我们提供了两张虚拟表,这是理解触发器的关键。它们就是 inserted 和 deleted,作用如下:
| 操作 | Inserted 表 | Deleted 表 |
|---|---|---|
| INSERT | 新数据 | 空 |
| DELETE | 空 | 原数据 |
| UPDATE | 新数据 | 旧数据 |
有了这两张表,记录日志变得非常简单:
CREATE TRIGGER trg_UpdateLog
ON Student
AFTER UPDATE
AS
BEGIN
INSERT INTO StudentLog(StudentID, OldName, NewName, UpdateTime)
SELECT d.ID, d.Name, i.Name, GETDATE()
FROM deleted d
JOIN inserted i ON d.ID = i.ID
END四、触发器的常见应用场景
1. 数据审计(日志记录)
CREATE TRIGGER trg_InsertLog
ON Orders
AFTER INSERT
AS
BEGIN
INSERT INTO OrderLog(OrderID, CreateTime)
SELECT ID, GETDATE() FROM inserted
END2. 数据校验(防止非法数据)
以“禁止工资为负数”为例:
CREATE TRIGGER trg_CheckSalary
ON Employee
AFTER INSERT, UPDATE
AS
BEGIN
IF EXISTS (SELECT 1 FROM inserted WHERE Salary < 0)
BEGIN
ROLLBACK
RAISERROR('工资不能为负数',16,1)
END
END3. 维护关联数据(如库存)
当插入订单时自动扣减库存,这种逻辑用触发器处理非常自然。
五、触发器的注意事项(非常重要)
1. 触发器是“针对集合”的,不是单行
很多人容易犯的错误是以为插入的数据只有一行,于是写成:
SELECT @id = ID FROM inserted
千万不要这样写,一定要按照多行数据来处理,这是最基本的思维转变。
2. 避免在触发器中编写复杂业务逻辑
原因其实很简单:
调试起来非常困难
性能容易被拖垮
极易引发死锁
会拖累主业务 SQL 的执行速度
因此触发器最适合做的事情是:
✅ 校验
✅ 日志
✅ 简单的数据同步
而不该做的事情包括:
❌ 复杂的计算任务
❌ 调用外部接口
❌ 长事务逻辑
3. 谨慎使用 ROLLBACK
触发器中一旦执行 ROLLBACK,原来的 SQL 操作也会一并失败。因此必须慎重考虑。
4. 注意递归触发
如果触发器内部又修改了本表的数据,就可能造成无限循环。当然,你可以选择将其关闭:
ALTER DATABASE dbname SET RECURSIVE_TRIGGERS OFF
六、触发器与存储过程的区别
| 对比项 | 触发器 | 存储过程 |
|---|---|---|
| 是否自动执行 | 是 | 否 |
| 是否可传参 | 否 | 是 |
| 调用方式 | 系统触发 | 手动调用 |
| 使用场景 | 监听数据变化 | 业务逻辑处理 |
七、最佳实践总结
推荐使用场景:
数据审计日志
简单校验规则
防误操作保护
数据同步
不推荐使用场景:
核心业务逻辑
高并发复杂处理
跨系统调用
一句话原则:
触发器 = 数据层的“守门员”,不是业务层的“指挥官”。
八、结语
SQL Server 触发器是一把“双刃剑”:
用得好:能显著提升数据安全性与一致性
用不好:性能受损、维护成本急剧上升
建议始终遵循这个原则:
少用、慎用、简单用。
将复杂业务逻辑放在:
存储过程
服务层(Java / C#)
应用程序中处理
面试回答话术(简洁版)
“触发器主要用于实现复杂的业务完整性、审计日志、自动更新冗余统计字段以及软删除。但我清楚它的代价:隐式执行、难以调试、容易引发性能问题和死锁。
使用时我会特别注意:基于集合处理 inserted/deleted,绝不用游标或逐行操作;避免在触发器内进行耗时操作或开启新事务;关闭递归触发器(除非有明确需求);对批量操作做充分测试;优先考虑用约束、计算列或应用层逻辑替代触发器。
总的来说,触发器是最后的手段,能不用就不用;但在必须保证数据强一致性且无法用其他方法实现时,它是个有效的工具。”
