在SQL Server中,触发器是一种特殊的存储过程,它在特定的DML操作(INSERT、UPDATE、DELETE)执行后自动触发,常用于实现复杂的业务规则或数据完整性约束。本例主要探讨如何利用SQL Server的触发器来记录表的历史修改痕迹。
让我们了解SQL Server中的两个关键概念:`inserted`和`deleted`表。这两个表是系统自动创建的临时表,它们具有与触发器关联的表相同的列结构。`inserted`表保存了由INSERT或UPDATE操作导致的新增或更新后的行,而`deleted`表则存储了由DELETE或UPDATE操作导致的被删除或更新前的行。这些表只在触发器执行期间存在,并在触发器执行完毕后被删除。
SQL Server提供了两种类型的触发器:`INSTEAD OF`和`AFTER`触发器。`INSTEAD OF`触发器在DML操作发生前触发,允许你替代或阻止原始操作。它可以在表或视图上使用,以扩展视图的更新能力。而`AFTER`触发器则在DML操作完成并执行了所有约束检查后触发,主要用于执行额外的操作。
在实现历史修改记录功能时,我们通常使用`AFTER`触发器,因为它能够确保在记录变更信息之后再执行其他数据库操作。例如,我们可以创建以下两个触发器:
1. `tr_product_i`:这是一个`AFTER INSERT`触发器,当有新的记录插入`product`表时,它会将插入的行的信息(包括插入命令和执行时间)复制到`product_log`表中。
```sql
CREATE TRIGGER tr_product_i
ON product
AFTER INSERT
AS
IF @@rowcount = 0 -- 避免在无影响行时触发
RETURN
INSERT INTO product_log (name, description, unit_cost, pub_time, sqlcomm, exectime)
SELECT name, description, unit_cost, pub_time, 'insert', GETDATE()
FROM inserted
```
2. `tr_product_u`:这是一个`AFTER UPDATE`触发器,当`product`表中的记录被更新时,它将更新的行信息(包括更新命令和执行时间)记录到`product_log`表。
```sql
CREATE TRIGGER tr_product_u
ON product
AFTER UPDATE
AS
IF @@rowcount = 0
RETURN
INSERT INTO product_log (name, description, unit_cost, pub_time, sqlcomm, exectime)
SELECT name, description, unit_cost, pub_time, 'update', GETDATE()
FROM inserted
WHERE NOT EXISTS (SELECT 1 FROM deleted WHERE deleted.id = inserted.id)
-- 上述条件用于避免在没有实际更改的更新操作时插入记录
```
同时,我们还需要一个`AFTER DELETE`触发器`tr_product_d`来记录删除操作:
```sql
CREATE TRIGGER tr_product_d
ON product
AFTER DELETE
AS
IF @@rowcount = 0
RETURN
INSERT INTO product_log (name, description, unit_cost, pub_time, sqlcomm, exectime)
SELECT name, description, unit_cost, pub_time, 'delete', GETDATE()
FROM deleted
```
通过这种方式,每次对`product`表进行INSERT、UPDATE或DELETE操作时,`product_log`表都会记录下相应的操作及其时间戳,从而实现了对表历史修改痕迹的完整跟踪。这样的设计对于日后的数据问题排查、审计或者数据分析都有着重要的作用。需要注意的是,频繁的触发器使用可能会影响数据库性能,因此在设计时应考虑效率和存储空间等因素。