SQL Server数据库中有哪些触发器

发布时间:2021-08-13 14:42:53 作者:Leah
来源:亿速云 阅读:511
# 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

3.2 INSTEAD OF触发器

基本特点

创建语法

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

3.3 inserted和deleted表

所有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

四、DDL触发器详解

4.1 基本概念

4.2 常见事件类型

事件组 具体事件示例
CREATE_TABLE CREATE TABLE
ALTER_PROCEDURE ALTER PROCEDURE
DROP_VIEW DROP VIEW
GRANT_DATABASE GRANT语句在数据库权限上的操作

4.3 创建语法

CREATE TRIGGER trigger_name
ON { DATABASE | ALL SERVER }
FOR { DDL_event | DDL_event_group }
AS
BEGIN
    -- 触发器逻辑
END

4.4 实际案例

防止表被删除

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

五、LOGON触发器

5.1 基本概念

5.2 创建语法

CREATE TRIGGER trigger_name
ON ALL SERVER
FOR LOGON
AS
BEGIN
    -- 触发器逻辑
END

5.3 实际案例

限制登录时间

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

六、触发器的管理与优化

6.1 查看触发器

-- 查看表上的DML触发器
SELECT * FROM sys.triggers WHERE parent_id = OBJECT_ID('TableName')

-- 查看数据库DDL触发器
SELECT * FROM sys.database_triggers

-- 查看服务器级触发器
SELECT * FROM sys.server_triggers

6.2 修改触发器

ALTER TRIGGER trigger_name
-- 其余部分与CREATE TRIGGER相同

6.3 禁用/启用触发器

-- 禁用表触发器
DISABLE TRIGGER trigger_name ON table_name

-- 启用数据库触发器
ENABLE TRIGGER trigger_name ON DATABASE

6.4 性能优化建议

  1. 保持精简:触发器应快速执行
  2. 避免递归:使用RECURSIVE_TRIGGERS数据库选项控制
  3. 注意事务:长时间运行的触发器会阻塞其他操作
  4. 避免嵌套:嵌套触发器最多32层

七、触发器的最佳实践

  1. 文档记录:为每个触发器添加注释说明用途
  2. 错误处理:包含完善的错误处理逻辑
  3. 测试验证:确保触发器不影响正常业务操作
  4. 避免过度使用:复杂业务逻辑考虑用存储过程
  5. 版本控制:将触发器脚本纳入版本管理系统

结语

SQL Server提供了丰富多样的触发器类型,从DML、DDL到LOGON触发器,为数据库开发人员提供了强大的自动化工具。合理使用触发器可以显著提高数据完整性和系统安全性,但同时也需要注意性能影响和管理复杂度。掌握各类触发器的特点和应用场景,将使您能够设计出更加健壮、高效的数据库解决方案。 “`

注:本文实际字数为约3500字,要达到4050字可考虑以下扩展方向: 1. 增加更多实际案例(每种触发器补充1-2个案例) 2. 添加”触发器与事务的交互”专门章节 3. 深入讲解触发器执行上下文和安全考虑 4. 比较触发器与约束、存储过程的适用场景 5. 添加性能测试数据和优化案例

推荐阅读:
  1. SQL Server 如何清空数据库所有表数据
  2. SQL server数据库中数据完整性的分析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

sqlserver

上一篇:python中如何将源文件打包成exe文件

下一篇:MySQL数据库中怎么定期删除日志表

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》