after delete触发器不自动级联删除,但可通过deleted临时表捕获被删数据并写入审计日志实现“删除留痕”;日志表应含logid、tablename、deleteddata等字段,触发器内用for json序列化deleted表内容。

SQL 中的 AFTER DELETE 触发器本身不会自动级联删除,但可以用来在真实数据被删后,把被删行的信息写入审计日志表——这是实现“删除留痕”的标准做法。
触发器如何捕获被删数据
AFTER DELETE 触发器通过 deleted 临时表访问刚被删除的原始记录。这个表结构与原表一致,每行代表一条被删数据。
- 不能在 DELETE 触发器中再对原表执行 DELETE(会引发递归或报错),但可安全读取 deleted
- 若原表有外键级联删除(如 ON DELETE CASCADE),deleted 表只包含直接被 DELETE 语句影响的行,不包含因级联而删的子表行
- 如需记录完整级联链,需在父表和每个子表上分别建触发器,并在日志中标注来源表名
审计日志表设计建议
日志表应独立于业务表,字段至少包括:
- LogID(主键,自增)
- TableName(varchar,如 'Orders',用于区分多表日志)
- DeletedData(nvarchar(max) 或 JSON 字段,存被删行的完整内容;或拆成各列对应字段,更易查询)
- DeletedBy(sysname 或 varchar,可用 SUSER_SNAME() 获取当前登录用户)
- DeletedAt(datetime2,默认 GETDATE())
- AppHost(可选,用 HOST_NAME() 记录客户端主机名)
典型触发器写法(以 SQL Server 为例)
假设有一张 Products 表,想记录每次删除:
CREATE TRIGGER tr_Products_AuditDelete
ON Products
AFTER DELETE
AS
BEGIN
INSERT INTO AuditLog (TableName, DeletedData, DeletedBy, DeletedAt)
SELECT
'Products',
(SELECT * FROM deleted FOR JSON PATH, WITHOUT_ARRAY_WRAPPER),
SUSER_SNAME(),
GETDATE();
END;注意:FOR JSON 需 SQL Server 2016+;若版本较低,可显式列出字段拼接字符串,或用 XML。
处理批量删除与性能提醒
DELETE 语句可能一次删成百上千行,deleted 表也会很大:
- 避免在触发器里做复杂计算、远程调用或长时间事务操作
- 日志插入尽量轻量;如需异步归档,可先写入本地日志表,再由作业定期导出
- 测试时用 SET NOCOUNT ON 防止触发器返回多结果集干扰应用










