本示例介绍如何在SQL Server中创建和使用触发器,通过实际案例展示其功能及应用场景,帮助理解数据库自动化维护。
触发器是一种特殊的存储过程,在SQL Server中不能被显式调用,而是在向表插入、更新或删除记录时自动激活。因此,它们可以用来实施复杂的完整性约束。
每当有数据更改操作发生(如INSERT, UPDATE, DELETE),SQL Server会自动生成两个临时表格:Inserted和Deleted。这两个表的结构与触发器作用的目标表一致,并且仅存在于内存中,在触发器执行完成后即被删除。其中,Deleted表存放由于DELETE或UPDATE语句而从表中移除的所有行;Inserted表则存储由INSERT或UPDATE操作添加到目标表中的所有新记录。
SQL Server 2000支持两种类型的触发器:INSTEAD OF和AFTER。前者替代执行引发它的T-SQL语句,可用于扩展视图的更新能力(除了表格之外)。后者在插入、更新或删除之后运行,并且可以在这些操作完成之前进行约束检查等操作。
如果INSERT, UPDATE 或 DELETE 语句违反了某种约束条件,则相应的After触发器将不会被执行。相反地,INSTEAD OF 触发器可以先于对数据的更改执行,在这种情况下它能够预先处理一些可能会导致错误的操作,并且可以在插入和删除之前进行必要的检查。
创建触发器的基本语法如下:
```sql
CREATE TRIGGER trigger_name
ON {table_name | view_name}
{FOR|AFTER|INSTEAD OF} [INSERT, UPDATE, DELETE]
AS sql_statement
```
示例:
1. 在Orders表中建立一个After触发器,用于检查goods表中的货品状态。如果状态为正在整理(status=1),则阻止订单插入。
```sql
CREATE TRIGGER orderinsert
ON orders
AFTER INSERT
AS
IF (SELECT status FROM goods WHERE name = (SELECT goodsname FROM inserted)) = 1 BEGIN PRINT The goods are being processed. Order cannot be committed. ROLLBACK TRANSACTION END
```
2. 在Orders表建立触发器,当添加新的订单时减少Goods表中的库存。
```sql
CREATE TRIGGER orderinsert1
ON orders
AFTER INSERT
AS UPDATE goods SET storage = storage - (SELECT quantity FROM inserted WHERE goods.name=goodsname)
```
3. 在Goods表中创建删除触发器,实现级联删除功能。
```sql
CREATE TRIGGER goodsdelete
ON goods
AFTER DELETE
AS DELETE from orders where goodsname in(SELECT name FROM deleted)
```
4. 创建防止手动修改订单日期的更新触发器。
```sql
CREATE TRIGGER orderdateupdate ON orders AFTER UPDATE AS IF update(orderdate) BEGIN raiserror(Order date cannot be modified,10,1) ROLLBACK TRANSACTION END
```
5. 在Orders表中创建一个插入触发器,确保添加到该表中的所有货品名称都已在Goods表中存在。
```sql
CREATE TRIGGER orderinsert3 ON orders AFTER INSERT AS IF (SELECT COUNT(*) FROM goods WHERE name = (SELECT goodsname FROM inserted))=0 BEGIN PRINT No entry in Goods for this Order ROLLBACK TRANSACTION END
```
6. 在info_details表上创建触发器,用于同步插入、更新和删除操作到索引表中。
```sql
-- 插入触发器示例
CREATE TRIGGER tri_infoDetails_i ON info_details AFTER INSERT AS DECLARE @id INT BEGIN SELECT @id=id FROM inserted; INSERT INTO info_details_index(TYPE, TITLE, content, POST_TIME, FLAG) SELECT type,title,content,getdate(),1 FROM info_details WHERE id=@id END
-- 更新触发器示例
CREATE TRIGGER tri_infoDetails_u ON info_details AFTER UPDATE AS DECLARE @id INT BEGIN IF EXISTS(SELECT 1 FROM inserted) AND EXISTS (SELECT 1 FROM deleted) BEGIN SELECT @id=id FROM inserted; INSERT INTO info_details_index(TYPE, TITLE,content, POST_TIME, FLAG) SELECT type,title,content,getdate(),-1 FROM info_details WHERE id=@id; INSERT INTO info_details_index(TYPE,TITLE,content,POST_TIME,FLAG) SELECT type,title,content,getdate(),1 FROM info_details WHERE id=@id END END
-- 删除触发器示例
CREATE TRIGGER tri_infoDetails_d ON info_details AFTER DELETE AS DECLARE @id INT BEGIN IF EXISTS(SELECT 1 FROM deleted) BEGIN INSERT INTO info_details_index(TYPE,TITLE,POST_TIME,FLAG) SELECT type,title,getdate(),-1 FROM deleted WHERE id=@id; END END;
```