SQL触发器实战:银行系统数据完整性控制

一、触发器基础概念

  • 触发器的定义:一种由插入(INSERT)、更新(UPDATE)、删除(DELETE)事件自动触发的特殊存储过程

  • 触发器的分类:AFTER(后触发)触发器、INSTEAD OF(替代触发器)

  • 本实验重点使用的是 AFTER 触发器

二、inserted 与 deleted 虚拟表

  • inserted表:存放 INSERT 或 UPDATE 操作产生的新数据行

  • deleted表:存放 DELETE 或 UPDATE 操作中被删除的旧数据行

  • 这两个表只在触发器作用域内存在,是触发器中数据访问的核心对象

三、触发器的创建与管理

  • 使用 CREATE TRIGGER创建触发器

  • 指定触发事件:ON 表名 AFTER INSERT / DELETE / UPDATE

  • 在触发器中使用 T-SQL 逻辑控制事务与业务规则

四、事务控制与数据约束

  • 使用 ROLLBACK TRANSACTION撤销违规的数据操作

  • 使用 RAISERROR抛出业务错误提示

  • 在触发器内结合 UPDATEDELETE实现联动数据维护

  • 触发器与 CHECK约束、PRIMARY KEYFOREIGN KEY的关系与区别

五、数据完整性控制(核心目标)

  • 实体完整性 :主键约束(PRIMARY KEY

  • 域完整性CHECK约束、数据类型、长度校验(LEN()LEFT()

  • 参照完整性:通过触发器实现级联删除与备份(弥补外键未定义的场景)

  • 业务完整性:余额校验、大额交易监控等业务规则由触发器实现

六、实际应用能力点

  • 利用触发器实现:

    • 业务规则校验(取款余额、卡号格式)

    • 自动数据更新(账户余额联动)

    • 级联操作(删除账户同时清理交易记录)

    • 数据备份与审计(反洗钱监测、历史数据归档)

七、实验概述

1. 实验目的

(1)理解并掌握 SQL Server 中触发器(Trigger)的工作原理;

(2)学会创建和使用 AFTER 触发器;

(3)能够利用触发器实现业务规则约束、数据自动维护与安全控制;

(4)通过实验加深对数据完整性控制机制的理解。

2. 实验环境

  • 硬件环境:个人计算机(PC)

  • 操作系统:Windows 10 / Windows 11

  • 数据库管理系统:Microsoft SQL Server

  • 开发语言:Transact-SQL(T-SQL)

3. 实验准备(建库、建表、初始数据)

复制代码
CREATE DATABASE bankSystem;
GO
USE bankSystem;
GO

CREATE TABLE bank(
    cardID varchar(8) PRIMARY KEY,
    customerName varchar(12),
    currentMoney money
);

CREATE TABLE transInfo(
    cardID varchar(8) NOT NULL,
    transDate datetime NOT NULL,
    transType varchar(8)
        CONSTRAINT cttype CHECK(transType='存入' OR transType='支取'),
    transMoney money,
    PRIMARY KEY(cardID, transDate)
);

INSERT INTO bank VALUES ('10010001','张三',1000);
INSERT INTO bank VALUES ('10010002','李四',1);

八、实验内容与实现过程

实验 1:取款操作触发器(tri_insert_transInfo)

(1)实验要求

当向交易信息表 transInfo 插入取款("支取")记录时,判断取款金额是否会导致账户余额低于 1 元。若合法,则自动更新账户余额;若不合法,则撤销取款操作。

(2)触发器代码
复制代码
CREATE TRIGGER tri_insert_transInfo
ON transInfo
AFTER INSERT
AS
BEGIN
    DECLARE @cardID varchar(8),
            @transMoney money,
            @balance money;

    SELECT @cardID = cardID,
           @transMoney = transMoney
    FROM inserted;

    SELECT @balance = currentMoney
    FROM bank
    WHERE cardID = @cardID;

    IF (@balance - @transMoney < 1)
    BEGIN
        RAISERROR('余额不足,取款失败!',16,1);
        ROLLBACK TRANSACTION;
    END
    ELSE
    BEGIN
        UPDATE bank
        SET currentMoney = currentMoney - @transMoney
        WHERE cardID = @cardID;
    END
END;
GO
(3)测试代码
复制代码
-- 合法取款
INSERT INTO transInfo
VALUES('10010001','2026-05-21','支取',500);

-- 非法取款
INSERT INTO transInfo
VALUES('10010002','2026-05-21','支取',1);
(4)实验结果与分析

第一次取款操作成功,账户余额由 1000 更新为 500;第二次取款因余额不足被触发器阻止,系统提示错误并回滚事务,数据未发生变化。


实验 2:银行卡号合法性触发器(tri_insert_cusID)

(1)实验要求

在 bank 表中新增账户时,要求银行卡号必须为 8 位,且必须以"10"开头,否则撤销插入操作。

(2)触发器代码
复制代码
CREATE TRIGGER tri_insert_cusID
ON bank
AFTER INSERT
AS
BEGIN
    DECLARE @cardID varchar(8);

    SELECT @cardID = cardID FROM inserted;

    IF (LEN(@cardID) <> 8 OR LEFT(@cardID,2) <> '10')
    BEGIN
        RAISERROR('卡号必须为8位且以10开头!',16,1);
        ROLLBACK TRANSACTION;
    END
END;
GO
(3)测试代码
复制代码
-- 合法插入
INSERT INTO bank VALUES('10010003','王五',2000);

-- 非法插入
INSERT INTO bank VALUES('90010004','赵六',3000);
(4)实验结果与分析

合法卡号成功插入表中;非法卡号被触发器拦截,插入操作被回滚,保证了数据的规范性。


实验 3:账户注销触发器(trig_delete_cusInfo)

(1)实验要求

当删除 bank 表中的账户时,同时删除该账户的所有交易记录,并将账户信息与交易信息备份到 backupBank 和 backupTransInfo 表中。

(2)触发器代码
复制代码
CREATE TRIGGER trig_delete_cusInfo
ON bank
AFTER DELETE
AS
BEGIN
    -- 备份账户信息
    IF NOT EXISTS(SELECT * FROM sysobjects WHERE name='backupBank')
        SELECT * INTO backupBank FROM deleted;
    ELSE
        INSERT INTO backupBank SELECT * FROM deleted;

    -- 备份交易信息
    IF NOT EXISTS(SELECT * FROM sysobjects WHERE name='backupTransInfo')
        SELECT * INTO backupTransInfo
        FROM transInfo
        WHERE cardID IN (SELECT cardID FROM deleted);
    ELSE
        INSERT INTO backupTransInfo
        SELECT * FROM transInfo
        WHERE cardID IN (SELECT cardID FROM deleted);

    -- 删除交易记录
    DELETE FROM transInfo
    WHERE cardID IN (SELECT cardID FROM deleted);
END;
GO
(3)测试代码
复制代码
DELETE FROM bank WHERE cardID = '10010001';
(4)实验结果与分析

账户成功删除,相关交易记录被同步删除,同时备份表中保存了被删除的数据,实现了数据的安全回收。


实验 4:反洗钱监测触发器(trig_Cashin_check)

(1)实验要求

当发生金额大于等于 500 万的大额存入交易时,将卡号、姓名、交易金额和交易时间自动写入 susTable 表,供反洗钱分析使用。

(2)触发器代码
复制代码
CREATE TRIGGER trig_Cashin_check
ON transInfo
AFTER INSERT
AS
BEGIN
    IF NOT EXISTS(SELECT * FROM sysobjects WHERE name='susTable')
        SELECT bank.cardID,
               bank.customerName,
               inserted.transMoney,
               inserted.transDate
        INTO susTable
        FROM inserted
        JOIN bank ON inserted.cardID = bank.cardID
        WHERE inserted.transType = '存入'
          AND inserted.transMoney >= 5000000;
    ELSE
        INSERT INTO susTable
        SELECT bank.cardID,
               bank.customerName,
               inserted.transMoney,
               inserted.transDate
        FROM inserted
        JOIN bank ON inserted.cardID = bank.cardID
        WHERE inserted.transType = '存入'
          AND inserted.transMoney >= 5000000;
END;
GO
(3)测试代码
复制代码
INSERT INTO transInfo
VALUES('10010001','2026-05-21','存入',6000000);
(4)实验结果与分析

普通存款不会触发该机制;当存款金额达到 600 万时,系统自动将该交易记录写入 susTable,触发器运行正常,满足反洗钱业务需求。

相关推荐
半夜修仙1 小时前
Redis中Set数据类型的常见命令
java·数据库·redis·笔记·学习
oradh1 小时前
Oracle逻辑存储结构概述
数据库·oracle·逻辑存储结构·oracle逻辑存储结构概述
廿一夏1 小时前
MySql视图触发器函数存储过程
数据库·sql·oracle
hikktn1 小时前
Oracle 行锁 ORA-00054 高效重试机制实战:MERGE 批量更新 + FOR UPDATE NOWAIT 完整方案
数据库·oracle
￰meteor1 小时前
【数据库导学】
数据库
zxrhhm1 小时前
Oracle检查点Checkpoint深度解析
数据库·oracle
rising start1 小时前
三、深入理解MySQL索引底层
数据库·mysql
weixin_426150702 小时前
AI辅助Oracle容量规划:告别拍脑袋扩容
运维·数据库·人工智能·oracle
l1t2 小时前
DeepSeek总结的PostgreSQL 表访问方法
数据库·postgresql