MSSQL之十八 事务

举报
tea_year 发表于 2021/12/30 00:34:02 2021/12/30
【摘要】 事务(TRANSACTION)是作为单个逻辑工作单元执行的一系列操作,这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行 ,事务是一个不可分割的工作逻辑单元 . 事务必须具备以下四个属性,简称ACID 属性:原子性(Atomicity):事务是一个完整的操作。事务的各步操作是不可分的(原子的);要么都执行,要么都不执行一...

  
  1. 事务(TRANSACTION)是作为单个逻辑工作单元执行的一系列操作,这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行 ,事务是一个不可分割的工作逻辑单元 .
  2. 事务必须具备以下四个属性,简称ACID 属性:
  3. 原子性(Atomicity):事务是一个完整的操作。事务的各步操作是不可分的(原子的);要么都执行,要么都不执行
  4. 一致性(Consistency):当事务完成时,数据必须处于一致状态
  5. 隔离性(Isolation):对数据进行修改的所有并发事务是彼此隔离的,这表明事务必须是独立的,它不应以任何方式依赖于或影响其他事务
  6. 永久性(Durability):事务完成后,它对数据库的修改被永久保持,事务日志能够保持事务的永久性
  7. /*--举例:为什么需要事务--*/
  8. --同一银行,如都是农行的帐号,可以直接转账
  9. /*---------------建表-----------------*/
  10. --创建农行帐户表bank
  11. IF EXISTS(SELECT * FROM sysobjects WHERE name='bank')
  12. DROP TABLE bank
  13. GO
  14. CREATE TABLE bank
  15. (
  16. customerName CHAR(10), --顾客姓名
  17. cardID CHAR(10) NOT NULL , --卡号
  18. currentMoney MONEY --当前余额
  19. )
  20. GO
  21. /*---添加约束:根据银行规定,帐户余额不能少于1元,除非销户----*/
  22. ALTER TABLE bank
  23. ADD CONSTRAINT CK_currentMoney CHECK(currentMoney>=1)
  24. GO
  25. /*--插入测试数据:张三开户,开户金额为800 ;李四开户,开户金额1 ---*/
  26. INSERT INTO bank(customerName,currentMoney,cardId) VALUES('张三',1000,'1001 0001')
  27. INSERT INTO bank(customerName,currentMoney,cardId) VALUES('李四',1,'1002 0002')
  28. GO
  29. --查看结果
  30. delete from bank
  31. SELECT * FROM bank
  32. GO
  33. /*--转帐测试:张三希望通过转账,直接汇钱给李四1000元--*/
  34. --我们可能会这样这样写代码
  35. --张三的帐户少1000元,李四的帐户多1000元
  36. /***************开始
  37. UPDATE bank SET currentMoney=currentMoney-1000
  38. WHERE customerName='张三'
  39. UPDATE bank SET currentMoney=currentMoney+1000
  40. WHERE customerName='李四'
  41. *********结束/
  42. GO
  43. --再次查看结果,结果发现了什么严重的错误?如何解决呢?
  44. SELECT * FROM bank
  45. GO
  46. --恢复原来的数据
  47. --UPDATE bank SET currentMoney=currentMoney-1000 WHERE customerName='李四'
  48. SET NOCOUNT ON --不显示受影响的行数信息
  49. print '查看转帐事务前前前前前前的余额'
  50. SELECT * FROM bank
  51. GO
  52. /*--开始事务(指定事务从此处开始,后续的T-SQL语句都是一个整体--*/
  53. BEGIN TRANSACTION
  54. /*--定义变量,用于累计事务执行过程中的错误--*/
  55. DECLARE @errorSum INT
  56. SET @errorSum=0 --初始化为0,即无错误
  57. /*--转帐:张三的帐户少1000元,李四的帐户多1000元*/
  58. UPDATE bank SET currentMoney=currentMoney-200 WHERE customerName='张三'
  59. SET @errorSum=@errorSum+@@error --累计是否有错误
  60. UPDATE bank SET currentMoney=currentMoney+200 WHERE customerName='李四'
  61. SET @errorSum=@errorSum+@@error --累计是否有错误
  62. print '查看转帐事务过程中中中中中中的余额'
  63. SELECT * FROM bank
  64. /*--根据是否有错误,确定事务是提交还是撤销---*/
  65. IF @errorSum<>0 --如果有错误
  66. BEGIN
  67. print '交易失败,回滚事务'
  68. ROLLBACK TRANSACTION
  69. END
  70. ELSE
  71. BEGIN
  72. print '交易成功,提交事务,写入硬盘,永久的保存'
  73. COMMIT TRANSACTION
  74. END
  75. GO
  76. print '查看转帐事务后后后后后后后的余额'
  77. SELECT * FROM bank
  78. GO
  79. --*******************************案例一
  80. --@@rowcount 返回受上一语句影响的行数。
  81. --select @@rowcount
  82. --select @@error
  83. create table tab1
  84. (
  85. stu_id int primary key,
  86. stu_name varchar(5),
  87. stu_age int,
  88. stu_height int
  89. )
  90. create table tab2
  91. (
  92. stu_id int primary key,
  93. stu_name varchar(5),
  94. stu_age int,
  95. stu_height int
  96. )
  97. -----------------------------开始事务------------------------------------------------------
  98. begin transaction
  99. insert into tab1 (stu_id,stu_name,stu_age,stu_height) values(1,'小明',22,180)
  100. if @@error <> 0 --or @@rowcount <> 1
  101. goto seed
  102. insert into tab1 (stu_id,stu_name,stu_age,stu_height) values(1,'小黄',23,150)
  103. if @@error <> 0 --or @@rowcount <> 1
  104. goto seed
  105. insert into tab1 (stu_id,stu_name,stu_age,stu_height) values(1,'小李',24,190)
  106. if @@error <> 0 --or @@rowcount <> 1
  107. goto seed
  108. insert into tab1 (stu_id,stu_name,stu_age,stu_height) values(4,'小张',25,176)
  109. seed:
  110. --print @@error
  111. if @@error <> 0 or @@rowcount <> 1
  112. begin
  113. --select @@error
  114. --select @@rowcount as ssss
  115. rollback transaction
  116. print '发生错误提交无法完成!!!!'
  117. end
  118. else
  119. begin
  120. commit transaction
  121. print '无错误发生提交正常!!!'
  122. end
  123. -------------------------------结束事务--------------------------------------------------
  124. delete from tab1
  125. select * from tab1
  126. truncate table tab1
  127. drop table tab1
  128. drop table tab2
  129. ---------------------------------------------------------------------------------------------
  130. Select a,b,c into tab1 from tab2 where a=2
  131. If @@rowcount=0 Print "no rows were copied"
  132. SELECT CONVERT(char(5), 3.147) AS 'CHAR(1)',
  133. CONVERT(char(5), 3.147) AS 'CHAR(3)',
  134. CONVERT(char(120), 3.147) AS 'CHAR(5)'
  135. GO
  136. --**************************************************************案例2
  137. use master
  138. go
  139. create table 物品管理数据表
  140. (
  141. 部门 varchar(10),
  142. 物品 varchar(10),
  143. 数量 int,
  144. CONSTRAINT CK_物品管理数据表 CHECK (数量 > 0)
  145. )
  146. insert 物品管理数据表 (部门,物品,数量) values('财务部','办公桌',2)
  147. insert 物品管理数据表 (部门,物品,数量) values('业务部','办公桌',10)
  148. insert 物品管理数据表 (部门,物品,数量) values('管理部','办公桌',5)
  149. insert 物品管理数据表 (部门,物品,数量) values('业务部','会议桌',5)
  150. insert 物品管理数据表 (部门,物品,数量) values('研发部','会议桌',7)
  151. insert 物品管理数据表 (部门,物品,数量) values('生产部','会议桌',8)
  152. go
  153. select * from 物品管理数据表
  154. truncate table 物品管理数据表
  155. drop table 物品管理数据表
  156. --显式事务
  157. -------------------------事务开始----------------------------------------
  158. Begin Transaction --开始事务
  159. update 物品管理数据表
  160. set 数量 = 数量 + 1
  161. where 部门='业务部' and 物品='办公桌'
  162. if @@error>0 --or @@rowcount<>1
  163. begin
  164. goto error1
  165. end
  166. update 物品管理数据表
  167. set 数量 = 数量 - 1
  168. where 部门='财务部' and 物品='办公桌'
  169. error1:
  170. if @@error>0 --or @@rowcount<>1
  171. begin
  172. print '毛病!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
  173. rollback transaction --取消并回滚事务
  174. end
  175. else
  176. --print '毛病!!!'
  177. commit tran --提交事务
  178. select @@rowcount
  179. select @@error
  180. -------------------------事物结束----------------------------------------
  181. -------------------------查询结果----------------------------------------
  182. select * from 物品管理数据表
  183. --**********************************隐形事务
  184. set implicit_transactions on --
  185. --set implicit_transactions off --关闭隐含事务模式
  186. --隐性事务一般只使用在测试或查错上,由于会占用大量资源,
  187. --因此并不建议在数据库实际运作时使用。
  188. --**********************************
  189. create table 物品管理
  190. (
  191. 物品id int not null primary key,
  192. 物品名称 char(10),
  193. 物品数量 int,
  194. 部门 char(10)
  195. )
  196. insert into 物品管理 (物品id,物品名称,物品数量,部门) values(1,'桌子',12,'行政部')
  197. insert into 物品管理 (物品id,物品名称,物品数量,部门) values(2,'板凳',23,'学术部')
  198. insert into 物品管理 (物品id,物品名称,物品数量,部门) values(3,'书架',33,'市场部')
  199. insert into 物品管理 (物品id,物品名称,物品数量,部门) values(4,'电脑',22,'人事部')
  200. insert into 物品管理 (物品id,物品名称,物品数量,部门) values(5,'杯子',6,'财务部')
  201. insert into 物品管理 (物品id,物品名称,物品数量,部门) values(6,'鼠标',45,'组织部')
  202. select * from 物品管理
  203. ---------------------------------------事务开始---------------------------------------------
  204. begin transaction object
  205. insert into 物品管理 (物品id,物品名称,物品数量,部门) values(7,'C语言',2,'开发部')
  206. save transaction jet
  207. insert into 物品管理 (物品id,物品名称,物品数量,部门) values(8,'Java',9,'开发部')
  208. if @@error <> 0
  209. begin
  210. rollback tran jet
  211. print '输入记录出现问题,请重新检查!!!'
  212. end
  213. commit tran object
  214. ---------------------------------------事务结束---------------------------------------------
  215. truncate table 物品管理
  216. drop table 物品管理
  217. select * from 物品管理
  218. ---*************************************************************事务保存点2
  219. begin tran affair
  220. ....... -- 操作语句
  221. save tran temptran
  222. ...... -- 操作语句
  223. if (@@error <> 0)
  224. rollback tran temptran -- 回滚到事务保存点
  225. else
  226. commit tran affair
  227. ----------------------示 例----------------------------------
  228. create table stu_info
  229. (
  230. stu_id int primary key not null,
  231. stu_name varchar(5),
  232. stu_age int,
  233. stu_height int
  234. )
  235. insert into stu_info (stu_id,stu_name,stu_age,stu_height) values(1,'小明',22,180)
  236. insert into stu_info (stu_id,stu_name,stu_age,stu_height) values(2,'小黄',23,150)
  237. insert into stu_info (stu_id,stu_name,stu_age,stu_height) values(3,'小张',25,176)
  238. insert into stu_info (stu_id,stu_name,stu_age,stu_height) values(4,'小王',26,164)
  239. insert into stu_info (stu_id,stu_name,stu_age,stu_height) values(5,'小兵',24,170)
  240. ------------------------------开始事务-------------------------------------
  241. begin transaction stu
  242. delete from stu_info
  243. where stu_id = 1
  244. save transaction protec
  245. update stu_info
  246. set stu_name = '红旗'
  247. where stu_id in (3,5)
  248. if @@error > 0 or @@rowcount <> 1
  249. rollback tran protec
  250. else
  251. commit transaction stu
  252. ----------------结束事务--------------------------------------------------
  253. select * from stu_info
  254. truncate table stu_info
  255. --**************************************************************锁
  256. select suser_sid('Arwen')
  257. select suser_sname(0x2EBCE6E90123D24AA542D8F538F278AD)
  258. select user_name(3)
  259. select user_id('guest')
  260. -----------------------------------------------------------------------------------------------------------------------------
  261. use northwind
  262. SELECT *
  263. FROM Employees WITH (nolock) --这个语句就提供出了所有的数据,包括正在被其它处理器使用的数据,所以,得出的数据可能是脏数据,但是对于任务而言并没有很大的影响。
  264. UPDATE
  265. Employees WITH (tablock)
  266. SET Title='Test' -- 这个例子就是更新表中所有的行,所以使用了一个表锁。
  267. /*
  268. FASTFIRSTROW —选取结果集中的第一行,并将其优化
  269. HOLDLOCK —持有一个共享锁直至事务完成
  270. NOLOCK —不允许使用共享锁或独享锁。这可能会造成数据重写或者没有被确认就返回的情况;因此,就有可能使用到脏数据。这个提示只能在SELECT中使用。
  271. PAGLOCK —锁表格
  272. READCOMMITTED —只读取被事务确认的数据。这就是SQL Server的默认行为。
  273. READPAST —跳过被其它进程锁住的行,所以返回的数据可能会忽略行的内容。这也只能在SELECT中使用。
  274. READUNCOMMITTED —等价于NOLOCK.
  275. REPEATABLEREAD —在查询语句中,对所有数据使用锁。这可以防止其它的用户更新数据,但是新的行可能被其它的用户插入到数据中,并且被最新访问该数据的用户读取。
  276. ROWLOCK —按照行的级别来对数据上锁。SQL Server通常锁到页或者表级别来修改行,所以当开发者使用单行的时候,通常要重设这个设置。
  277. SERIALIZABLE —等价于HOLDLOCK.
  278. TABLOCK —按照表级别上锁。在运行多个有关表级别数据操作的时候,你可能需要使用到这个提示。
  279. UPDLOCK —当读取一个表的时候,使用更新锁来代替共享锁,并且保持一直拥有这个锁直至事务结束。它的好处是,可以允许你在阅读数据的时候可以不需要锁,并且以最快的速度更新数据。
  280. XLOCK —给所有的资源都上独享锁,直至事务结束。
  281. */
  282. --*****************************************************************脏读
  283. create database bank
  284. go
  285. use bank
  286. go
  287. create table student
  288. (
  289. stud_id int,
  290. stud_name char(10),
  291. grade int
  292. )
  293. drop table student
  294. insert into student(stud_id,stud_name,grade)
  295. values(1,'小贵子',79)
  296. insert into student(stud_id,stud_name,grade)
  297. values(2,'小春子',98)
  298. insert into student(stud_id,stud_name,grade)
  299. values(3,'小溜子',68)
  300. insert into student(stud_id,stud_name,grade)
  301. values(4,'小毛子',86)
  302. delete from student
  303. select * from student
  304. ===================================================
  305. --set implicit_transactions on
  306. --set implicit_transactions off
  307. ------------------------------------------------------------------------
  308. --========================事务缺陷======================================
  309. --脏读
  310. begin transaction
  311. update student
  312. set grade=100
  313. where stud_id=1
  314. if @@error >0
  315. rollback transaction
  316. commit transaction
  317. --=======================不可重复读==============================
  318. --事务查询
  319. set transaction isolation level
  320. repeatable read
  321. ---============================================
  322. set transaction isolation level
  323. repeatable read
  324. begin transaction
  325. select * from student
  326. --where stud_id=1
  327. commit transaction
  328. --=============================================
  329. --事务一
  330. set transaction isolation level
  331. repeatable read
  332. begin transaction
  333. update student
  334. set grade=220
  335. where stud_id=1
  336. commit transaction
  337. --事务二
  338. set transaction isolation level
  339. repeatable read
  340. begin transaction
  341. select * from student
  342. where stud_id=1
  343. commit transaction
  344. --************************隔离级别
  345. --隔离级别
  346. 级别一 read uncommitted
  347. 级别二 read committed
  348. 级别三 repeatable read
  349. 级别四 serializable
  350. set transaction isolation level
  351. repeatable read
  352. begin transaction
  353. select * from student
  354. where stud_id=1
  355. commit transaction


文章来源: aaaedu.blog.csdn.net,作者:tea_year,版权归原作者所有,如需转载,请联系作者。

原文链接:aaaedu.blog.csdn.net/article/details/52389360

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。