SQL 事务(Transaction)完整版学习笔记(含转账案例+存储过程+异常捕获)
一、事务核心概念必考简答题1. 事务定义事务(TRANSACTION)是作为单个逻辑工作单元执行的一系列操作。多个操作作为一个整体向系统提交要么全部执行成功要么全部不执行回滚事务是不可分割的工作逻辑单元。2. 事务四大特性ACID 必背原子性(Atomicity)事务整体不可拆分所有操作同时成功或同时失败回滚无部分执行情况。一致性(Consistency)事务执行前后数据库数据始终保持合法、一致的状态不会出现数据错乱。隔离性(Isolation)多个并发事务相互独立、互不干扰彼此隔离运行。永久性(Durability)事务提交成功后对数据库的修改永久生效不会丢失。3. 事务三大分类1自动提交事务默认模式SQL Server 默认机制每条独立T-SQL语句都是一个单独事务执行成功自动提交失败自动回滚。2显式事务重点、最常用手动通过begin transaction开启事务手动控制commit提交、rollback回滚适用于多语句联动业务转账、增减库存等。3隐性事务开启开关SET IMPLICIT_TRANSACTIONS ON后后续所有T-SQL语句自动开启事务需手动提交/回滚无需手动写开启语句。二、无事务的业务BUG反面案例1. 创建银行卡表测试数据-- 创建银行卡资金表带余额校验余额必须大于1规范字段类型 create table CardNew ( StudentId int identity(1000,1) primary key not null, StudentName varchar(10) not null, CurrentMoney money check(CurrentMoney 1) ) -- 初始化测试数据 insert into CardNew(StudentName,CurrentMoney) values(赵云,1400) insert into CardNew(StudentName,CurrentMoney) values(刘备,1500) insert into CardNew(StudentName,CurrentMoney) values(关羽,1600) insert into CardNew(StudentName,CurrentMoney) values(曹操,1700) -- 【BUG场景】无事务转账典型数据错乱问题 -- 1001刘备余额1500转出1000后剩余500符合check约束可执行 update CardNew set CurrentMoneyCurrentMoney-1000 where StudentId1001 -- 1002关羽转入1000 update CardNew set CurrentMoneyCurrentMoney1000 where StudentId1002 -- 查看数据 select * from CardNew -- 【手动制造报错场景】重新初始化数据演示BUG truncate table CardNew insert into CardNew(StudentName,CurrentMoney) values(赵云,1400) insert into CardNew(StudentName,CurrentMoney) values(刘备,1500) insert into CardNew(StudentName,CurrentMoney) values(关羽,1600) insert into CardNew(StudentName,CurrentMoney) values(曹操,1700) -- 错误场景1001转出1500余额0违反 CurrentMoney1 约束 update CardNew set CurrentMoneyCurrentMoney-1500 where StudentId1001 -- 本条正常执行导致转出失败、转入成功数据不一致 update CardNew set CurrentMoneyCurrentMoney1500 where StudentId1002 select * from CardNewBUG原因默认自动提交事务两条update语句相互独立前一句报错回滚后一句正常提交导致数据不一致。三、基础显式事务ERROR 错误捕获通过系统全局变量ERROR累计错误数判断是否回滚/提交事务解决转账数据错乱问题。-- 重置测试数据 truncate table CardNew insert into CardNew(StudentName,CurrentMoney) values(赵云,1400) insert into CardNew(StudentName,CurrentMoney) values(刘备,1500) insert into CardNew(StudentName,CurrentMoney) values(关羽,1600) insert into CardNew(StudentName,CurrentMoney) values(曹操,1700) declare errorNum int -- 定义错误计数器 set errorNum0 begin transaction -- 手动开启显式事务 -- 转出操作余额清零触发约束报错 update CardNew set CurrentMoneyCurrentMoney-1500 where StudentId1001 set errorNumerrorNumERROR -- 累加SQL错误码 -- 转入操作 update CardNew set CurrentMoneyCurrentMoney1500 where StudentId1002 set errorNumerrorNumERROR -- 事务提交/回滚判断 if(errorNum 0) begin rollback transaction -- 任意步骤报错整体回滚 print 事务执行失败已全部回滚 end else begin commit transaction -- 无错误正常提交 print 事务执行成功数据已更新 end select * from CardNew四、基础转账事务存储过程可直接调用封装通用转账逻辑支持自定义入账账号、出账账号、转账金额适配所有转账场景。-- 存在则删除存储过程 if exists(select * from sysobjects where nameTest1) drop proc Test1 go -- 基础通用转账事务存储过程 create proc Test1 inAccount int, -- 入账账号 outAccount int, -- 出账账号 jine int -- 转账金额 as declare errorNum int set errorNum0 begin transaction -- 开启事务 -- 出账账号扣款 update CardNew set CurrentMoneyCurrentMoney-jine where StudentIdoutAccount set errorNumerrorNumERROR -- 入账账号加款 update CardNew set CurrentMoneyCurrentMoneyjine where StudentIdinAccount set errorNumerrorNumERROR -- 事务逻辑判断 if(errorNum 0) begin rollback transaction print 转账失败事务回滚 end else begin commit transaction print 转账成功事务提交 end go -- 测试1正常转账成功 truncate table CardNew insert into CardNew(StudentName,CurrentMoney) values(赵云,1400) insert into CardNew(StudentName,CurrentMoney) values(刘备,1500) insert into CardNew(StudentName,CurrentMoney) values(关羽,1600) insert into CardNew(StudentName,CurrentMoney) values(曹操,1700) exec Test1 1003,1000,300 select * from CardNew -- 测试2异常转账触发约束失败回滚 exec Test1 1003,1000,1200 select * from CardNew五、高级异常捕获TRY-CATCH 语法1. 基础TRY-CATCH异常捕获用于捕获代码运行异常避免程序中断可手动抛出错误、终止执行。-- 基础 TRY-CATCH 异常捕获语法 begin try -- 强制类型转换错误模拟业务异常 declare i int set i CAST(abc as int) print i end try begin catch -- 抛出自定义错误信息 raiserror(字符串无法转换为数字数据类型错误,16,1) print 代码执行异常已捕获错误 end catch2. TRY-CATCH 结合事务-- TRY-CATCH 事务 标准组合用法 begin tran begin try delete from StudentInfo where StudentId1000 -- 主动抛出异常测试回滚效果 raiserror(无此学生编号删除失败,16,1) commit tran -- 无异常则提交事务 print 执行成功事务已提交 end try begin catch print 代码执行出错事务已回滚 if(TRANCOUNT 0) rollback tran -- 存在未提交事务则回滚 end catch核心逻辑TRY包裹正常业务代码CATCH捕获所有异常只要出错立刻回滚事务保证数据一致。六、终极完整版转账存储过程双重校验业务判断双异常捕获整合业务逻辑校验 ERROR错误捕获 TRY-CATCH异常捕获企业级标准写法无漏洞、安全性最高。-- 终极完整版业务校验事务双重异常捕获 转账存储过程 if exists ( select * from sysobjects where nametest01) drop proc test01 go create proc test01 inAccount int, -- 入账账号 outAccount int, -- 出账账号 jine int -- 转账金额 as declare errorNum int set errorNum0 -- 第一层前置业务合法性校验拦截逻辑错误 -- 1. 转账金额不能为负数 if (jine 0) begin raiserror(转账金额不合法必须大于0,16,1) return end -- 2. 校验转出账号是否存在 if not exists (select 1 from CardNew where StudentIdoutAccount) begin raiserror(转出账户不存在,16,1) return end -- 3. 校验转入账号是否存在 if not exists (select 1 from CardNew where StudentIdinAccount) begin raiserror(转入账户不存在,16,1) return end -- 4. 校验转出账户余额是否充足 declare yue money select yue CurrentMoney from CardNew where StudentIdoutAccount if(yue jine) begin raiserror(账户余额不足无法转账,16,1) return end -- 第二层事务 双重错误捕获拦截系统SQL错误 begin tran -- 开启事务 begin try -- 转出扣款 update CardNew set CurrentMoneyCurrentMoney-jine where StudentIdoutAccount set errorNumerrorNumERROR -- 转入加款 update CardNew set CurrentMoneyCurrentMoneyjine where StudentIdinAccount set errorNumerrorNumERROR -- 捕获轻微SQL执行错误 if(errorNum 0) begin raiserror(SQL语句执行出错事务回滚,16,1) rollback transaction end else begin commit transaction print 转账业务执行成功 end end try begin catch -- 捕获严重异常防止事务悬挂 if(TRANCOUNT 0) begin rollback tran print 程序异常事务强制回滚 end return end catch go -- 测试调用 truncate table CardNew insert into CardNew(StudentName,CurrentMoney) values(赵云,1400) insert into CardNew(StudentName,CurrentMoney) values(刘备,1500) insert into CardNew(StudentName,CurrentMoney) values(关羽,1600) insert into CardNew(StudentName,CurrentMoney) values(曹操,1700) -- 正常转账 exec test01 1001,1000,200 select * from CardNew -- 异常测试余额不足 exec test01 1002,1000,2000 select * from CardNew七、核心考点总结考前必背事务作用保证多步关联操作数据一致性防止部分执行、数据错乱转账核心场景。ACID四大特性原子性、一致性、隔离性、永久性简答题必考。事务三语句begin transaction开启、commit提交、rollback回滚。错误捕获区别ERROR捕获单条SQL错误TRY-CATCH捕获所有运行异常严重错误。双层校验逻辑先业务人工校验金额、账号、余额再系统事务校验零漏洞。TRANCOUNT判断当前是否存在未提交的事务避免重复回滚报错。

相关新闻

004:C盘爆满怎么办?自制自动清理C盘小工具

004:C盘爆满怎么办?自制自动清理C盘小工具

🔥 个人主页: 杨利杰YJlio ❄️ 个人专栏: 《Windows 疑难杂症与工单复盘案例库》 《Sysinternals实战教程》 《WINDOWS教程》 《Windows PowerShell 实战》 《IOS插件分析测试》 《超简单:用Python让Excel飞起来》…

2026/10/14 6:21:22 阅读更多 →
003:C盘满了怎么清理?4种系统方法释放空间

003:C盘满了怎么清理?4种系统方法释放空间

🔥 个人主页: 杨利杰YJlio ❄️ 个人专栏: 《Windows 疑难杂症与工单复盘案例库》 《Sysinternals实战教程》 《WINDOWS教程》 《Windows PowerShell 实战》 《IOS插件分析测试》 《超简单:用Python让Excel飞起来》…

2026/10/6 16:06:01 阅读更多 →
04 Collection 与 Parent 的区别

04 Collection 与 Parent 的区别

04 Collection 与 Parent 的区别 一句话记忆:Collection 管“怎么分组和显示”,Parent 管“怎么一起运动”。 一、Collection 是什么 Collection 可以理解成 Blender 场景中的文件夹或资产分组。例如: BOF_ASSET ├─ BOF_LOD0 ├─ BOF_LOD1…

2026/10/11 2:16:07 阅读更多 →

最新新闻

海南旅游推荐系统:混合算法与实时数据处理实践

海南旅游推荐系统:混合算法与实时数据处理实践

1. 项目背景与核心价值海南作为国内热门旅游目的地,每年吸引数千万游客。但面对庞大的景区、酒店、餐饮等旅游资源,游客常常陷入"选择困难症"——攻略信息过时、个性化推荐缺失、行程规划不合理等问题普遍存在。这正是我们开发这套旅游推荐系统…

2026/10/14 6:21:26 阅读更多 →
SimpMusic 现代 Android 架构指南:Clean Architecture 分层、依赖注入与多模块化实战

SimpMusic 现代 Android 架构指南:Clean Architecture 分层、依赖注入与多模块化实战

音视频 【免费下载链接】SimpMusic A cross-platform music app using YouTube Music for backend 项目地址: https://gitcode.com/gh_mirrors/si/SimpMusic 点击查看 免费下载 导读 本文以仓库内 AI 开发规范文档 .claude/skills/android-architecture/SKILL.md …

2026/10/14 6:21:26 阅读更多 →
集团顶层设计不是画图:从战略澄清到落地作战地图的实战方法

集团顶层设计不是画图:从战略澄清到落地作战地图的实战方法

很多集团把顶层设计当成一个“写文档”的活,我见过最夸张的一次,项目组交了三百多页报告,封面烫金、装帧精美,可公司内部能讲清里面逻辑的人不超过三个。半年后回访,那本蓝图躺在书架最高层,连塑料封膜都没…

2026/10/14 6:21:26 阅读更多 →
微信小程序开发第一周:从零搭建最小页面到交互实战

微信小程序开发第一周:从零搭建最小页面到交互实战

第一周接触微信小程序开发,最常见的状态是:资料收藏了一堆,视频看了三集,代码一行没写。我自己带新人时就发现,week1 这个阶段最不该贪多,因为小程序虽然看起来只是网页开发的变体,但它的环境、…

2026/10/14 6:21:26 阅读更多 →
结算系统资金安全防护:幂等、对账与资损追回实践

结算系统资金安全防护:幂等、对账与资损追回实践

作为一名长期跟结算系统打交道的人,我对“资损”这两个字有着本能的敬畏。很多人觉得结算就是“算算账”:今天收了多少钱,该付出去多少,两边对得上不就行了。但真正做过这行的人都知道,结算根本不是简单的加减法&#…

2026/10/14 6:21:26 阅读更多 →
AnyPS5:用串流让PS5运行任意PC应用

AnyPS5:用串流让PS5运行任意PC应用

1. 从“AnyPS5”这个名字说起:它到底想解决什么问题第一次看到“AnyPS5”这个标题,我脑子里冒出来的第一个念头是:这大概率不是一个官方项目,而是一个带着强烈个人色彩的命名。为什么这么说?因为“Any”这个前缀在技术…

2026/10/14 6:20:26 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →