在SQL Server中,当对表执行DELETE操作时,系统会自动生成一个名为deleted的临时表,该表的结构与被删除数据的源表完全一致,存储了本次删除操作所影响的所有行的原始数据,因此可以通过查询deleted表来捕获被删除记录的所有字段信息。

deleted表的基本特性
deleted表是SQL Server触发器中特有的临时表,仅在触发器执行期间存在,触发结束后会自动销毁。它有以下核心特性:
- 结构与触发器的父表完全一致,包含所有字段定义
- 执行DELETE操作时,被删除的每一行数据都会被完整存入deleted表
- 执行UPDATE操作时,deleted表存储的是更新前的旧数据
- 执行INSERT操作时,deleted表为空
创建捕获删除记录的触发器
要实现捕获被删除记录的所有字段,首先需要创建针对目标表的DELETE触发器,然后在触发器内部查询deleted表即可。以下是基础的实现示例,假设我们要对名为Employee的员工表创建删除触发器。
-- 创建删除触发器,捕获Employee表被删除记录的所有字段
CREATE TRIGGER tr_Employee_Delete
ON Employee -- 触发器绑定的目标表
AFTER DELETE -- 触发时机为DELETE操作之后
AS
BEGIN
-- 设置不返回受影响行数,提升性能
SET NOCOUNT ON;
-- 使用SELECT * 查询deleted表的所有字段,捕获被删除的完整记录
-- 这里可以将查询结果插入到日志表,也可以做其他业务处理
INSERT INTO Employee_Delete_Log -- 假设已存在的删除日志表,结构与Employee一致
SELECT * FROM deleted; -- 从deleted表获取所有被删除的字段数据
-- 如果需要在控制台查看被删除的记录,也可以直接查询
-- SELECT * FROM deleted;
END
不同删除场景的适配处理
单条记录删除场景
当执行单条删除语句时,deleted表中只会存在一条记录,此时SELECT * FROM deleted会返回该条被删除记录的所有字段值,上述基础触发器即可正常处理。
-- 单条删除示例 DELETE FROM Employee WHERE EmployeeID = 1001; -- 触发tr_Employee_Delete触发器,deleted表中仅包含EmployeeID为1001的这条被删除记录
批量删除场景
当执行批量删除语句时,deleted表中会存储所有被删除的行,SELECT * FROM deleted会返回所有被删除记录的全部字段,触发器中的插入操作会将所有记录批量写入日志表,无需额外处理。
-- 批量删除示例,删除所有部门为IT的员工 DELETE FROM Employee WHERE Department = 'IT'; -- 触发tr_Employee_Delete触发器,deleted表中包含所有部门为IT的被删除员工记录
使用SELECT *的注意事项
虽然SELECT *可以快速获取deleted表的所有字段,但在实际使用中需要注意以下几点:
- 如果日志表的结构与源表不一致,直接使用SELECT *会导致字段不匹配报错,此时需要显式指定字段列表
- 如果后续源表新增或删除了字段,使用SELECT *的触发器不需要修改即可适配新的表结构,但是日志表也需要同步调整结构
- 如果只需要部分字段,建议显式指定需要的字段名,避免不必要的字段传输,提升性能
显式指定字段的替代方案
如果不需要所有字段,或者需要避免SELECT *的潜在问题,可以显式指定需要捕获的字段,示例如下:
-- 显式指定字段的删除触发器示例
CREATE TRIGGER tr_Employee_Delete_WithColumns
ON Employee
AFTER DELETE
AS
BEGIN
SET NOCOUNT ON;
-- 显式指定需要捕获的字段,避免SELECT *的问题
INSERT INTO Employee_Delete_Log_Partial(EmployeeID, EmployeeName, Department, DeleteTime)
SELECT EmployeeID, EmployeeName, Department, GETDATE() FROM deleted;
END
常见问题说明
很多开发者会疑惑为什么不能直接在触发器外查询deleted表,这是因为deleted表是触发器作用域内的临时表,仅在触发器执行期间存在,触发器执行结束后就会被自动清理,外部会话无法访问该表。另外,如果触发器是INSTEAD OF DELETE类型,需要手动处理删除逻辑,同时deleted表依然会存储原本要被删除的数据,使用方式是一致的。
SQL_Server触发器deleted表SELECT_*删除记录捕获修改时间:2026-06-17 10:57:19