您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# SQL Server数据库中有哪些触发器
## 引言
触发器(Trigger)是SQL Server数据库中一种特殊的存储过程,它会在特定事件发生时自动执行。触发器主要用于维护数据完整性、实现业务规则、审计数据变更等场景。本文将全面介绍SQL Server中的各类触发器,包括其分类、工作原理、创建方法以及实际应用案例。
---
## 一、触发器的基本概念
### 1.1 什么是触发器
触发器是绑定到表或视图上的数据库对象,当表或视图中发生特定数据操作事件(如INSERT、UPDATE、DELETE)时自动触发执行。
### 1.2 触发器的特点
- **自动执行**:无需手动调用
- **事件驱动**:响应特定DML或DDL操作
- **事务性**:作为触发语句事务的一部分
- **不可接收参数**:与存储过程不同
### 1.3 触发器的用途
- 数据完整性约束
- 级联操作
- 审计跟踪
- 业务规则实施
- 同步复制
---
## 二、SQL Server触发器的分类
### 2.1 按触发事件分类
#### 1. DML触发器(数据操作语言)
响应INSERT、UPDATE、DELETE操作,最常用的触发器类型。
**子类型:**
- AFTER触发器(SQL Server 2000之前称为FOR触发器)
- INSTEAD OF触发器
#### 2. DDL触发器(数据定义语言)
响应CREATE、ALTER、DROP等DDL操作。
#### 3. LOGON触发器
响应SQL Server登录事件。
### 2.2 按作用范围分类
| 类型 | 作用对象 | 示例 |
|-------------|-----------------------|-----------------------|
| 表级触发器 | 特定表 | 订单表的UPDATE触发器 |
| 数据库级触发器 | 当前数据库所有对象 | 防止表被删除的触发器 |
| 服务器级触发器 | 服务器实例所有数据库 | 登录审计触发器 |
---
## 三、DML触发器详解
### 3.1 AFTER触发器
#### 基本特点
- 在触发语句**成功执行后**激活
- 仅能定义在表上
- 可以针对同一操作定义多个触发器
#### 创建语法
```sql
CREATE TRIGGER trigger_name
ON table_name
AFTER {INSERT | UPDATE | DELETE}
AS
BEGIN
-- 触发器逻辑
END
CREATE TRIGGER tr_OrderAudit
ON Orders
AFTER INSERT, UPDATE
AS
BEGIN
INSERT INTO OrderAudit(OrderID, ChangeType, ChangeDate)
SELECT OrderID,
CASE WHEN EXISTS(SELECT * FROM deleted) THEN 'UPDATE' ELSE 'INSERT' END,
GETDATE()
FROM inserted
END
CREATE TRIGGER trigger_name
ON table_or_view_name
INSTEAD OF {INSERT | UPDATE | DELETE}
AS
BEGIN
-- 替代操作的逻辑
END
CREATE TRIGGER tr_InsteadOfInsert
ON SalesSummaryView
INSTEAD OF INSERT
AS
BEGIN
-- 将视图插入操作分解为对基表的操作
INSERT INTO Products(...) SELECT ... FROM inserted
INSERT INTO Sales(...) SELECT ... FROM inserted
END
所有DML触发器都可以访问两个特殊的临时表:
表名 | 内容 |
---|---|
inserted | INSERT操作的新数据;UPDATE操作的新值 |
deleted | DELETE操作的旧数据;UPDATE操作的旧值 |
典型应用:
-- 检查工资变更幅度
CREATE TRIGGER tr_CheckSalaryChange
ON Employees
AFTER UPDATE
AS
BEGIN
IF UPDATE(Salary)
BEGIN
IF EXISTS (
SELECT 1 FROM inserted i
JOIN deleted d ON i.EmployeeID = d.EmployeeID
WHERE ABS(i.Salary - d.Salary) > d.Salary * 0.2
)
BEGIN
RSERROR('Salary change exceeds 20%% limit', 16, 1)
ROLLBACK TRANSACTION
END
END
END
事件组 | 具体事件示例 |
---|---|
CREATE_TABLE | CREATE TABLE |
ALTER_PROCEDURE | ALTER PROCEDURE |
DROP_VIEW | DROP VIEW |
GRANT_DATABASE | GRANT语句在数据库权限上的操作 |
CREATE TRIGGER trigger_name
ON { DATABASE | ALL SERVER }
FOR { DDL_event | DDL_event_group }
AS
BEGIN
-- 触发器逻辑
END
CREATE TRIGGER tr_PreventTableDrop
ON DATABASE
FOR DROP_TABLE
AS
BEGIN
DECLARE @EventData XML = EVENTDATA()
DECLARE @SchemaName NVARCHAR(255) = @EventData.value('(/EVENT_INSTANCE/SchemaName)[1]', 'NVARCHAR(255)')
DECLARE @TableName NVARCHAR(255) = @EventData.value('(/EVENT_INSTANCE/ObjectName)[1]', 'NVARCHAR(255)')
IF @SchemaName = 'dbo' AND @TableName IN ('Customers', 'Orders')
BEGIN
RSERROR('Cannot drop core tables!', 16, 1)
ROLLBACK
END
END
CREATE TRIGGER tr_DdlAudit
ON DATABASE
FOR DDL_DATABASE_LEVEL_EVENTS
AS
BEGIN
DECLARE @EventData XML = EVENTDATA()
INSERT INTO DatabaseAudit(
EventType,
PostTime,
LoginName,
ObjectName,
CommandText
)
VALUES(
@EventData.value('(/EVENT_INSTANCE/EventType)[1]', 'NVARCHAR(100)'),
@EventData.value('(/EVENT_INSTANCE/PostTime)[1]', 'DATETIME'),
@EventData.value('(/EVENT_INSTANCE/LoginName)[1]', 'NVARCHAR(100)'),
@EventData.value('(/EVENT_INSTANCE/ObjectName)[1]', 'NVARCHAR(100)'),
@EventData.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]', 'NVARCHAR(MAX)')
)
END
CREATE TRIGGER trigger_name
ON ALL SERVER
FOR LOGON
AS
BEGIN
-- 触发器逻辑
END
CREATE TRIGGER tr_RestrictLoginTime
ON ALL SERVER
FOR LOGON
AS
BEGIN
IF ORIGINAL_LOGIN() = 'AppUser'
AND DATEPART(HOUR, GETDATE()) NOT BETWEEN 8 AND 20
BEGIN
ROLLBACK
RSERROR('Login not allowed outside business hours', 16, 1)
END
END
CREATE TRIGGER tr_LoginAudit
ON ALL SERVER
FOR LOGON
AS
BEGIN
INSERT INTO ServerAudit.dbo.LoginAudit(
LoginName,
LoginTime,
ClientHost,
ApplicationName
)
SELECT
ORIGINAL_LOGIN(),
GETDATE(),
EVENTDATA().value('(/EVENT_INSTANCE/ClientHost)[1]', 'NVARCHAR(100)'),
EVENTDATA().value('(/EVENT_INSTANCE/ApplicationName)[1]', 'NVARCHAR(100)')
END
-- 查看表上的DML触发器
SELECT * FROM sys.triggers WHERE parent_id = OBJECT_ID('TableName')
-- 查看数据库DDL触发器
SELECT * FROM sys.database_triggers
-- 查看服务器级触发器
SELECT * FROM sys.server_triggers
ALTER TRIGGER trigger_name
-- 其余部分与CREATE TRIGGER相同
-- 禁用表触发器
DISABLE TRIGGER trigger_name ON table_name
-- 启用数据库触发器
ENABLE TRIGGER trigger_name ON DATABASE
RECURSIVE_TRIGGERS
数据库选项控制SQL Server提供了丰富多样的触发器类型,从DML、DDL到LOGON触发器,为数据库开发人员提供了强大的自动化工具。合理使用触发器可以显著提高数据完整性和系统安全性,但同时也需要注意性能影响和管理复杂度。掌握各类触发器的特点和应用场景,将使您能够设计出更加健壮、高效的数据库解决方案。 “`
注:本文实际字数为约3500字,要达到4050字可考虑以下扩展方向: 1. 增加更多实际案例(每种触发器补充1-2个案例) 2. 添加”触发器与事务的交互”专门章节 3. 深入讲解触发器执行上下文和安全考虑 4. 比较触发器与约束、存储过程的适用场景 5. 添加性能测试数据和优化案例
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。