Zeon.cnblog.com

忙着长大...
|

云谷の风

园龄:4年11个月粉丝:21关注:6

2022-05-29 19:15阅读: 44评论: 0推荐: 0

MS SQL高级——事务与索引

事务与索引

什么是事务?

事务的概念及要求

  • 事务(TRANSACTION)是作为单个逻辑工作单元执行的一系列操作。
  • 多个操作作为一个整体向系统提交,要么都执行、要么都不执行。
  • 事务是一个不可分割的工逻辑单元。

银行转账过程就是一个事务

  • 它需要两条UPDATE语句来完成,这两条语句是一个整体。
  • 如果其中任一条出现错误,则整个转账业务也应取消,两个账户中的余额应恢复到原来的数据,从而确保转账前和转账后的余额不变。

事务的特性

事务必须具备以下四个属性:

  • 原子性(Atomicity):事务是一个完整的操作,事务的各步操作是不可分的,要么都执行,要么都不执行。
  • 一致性(Consistency):当事务完成时,数据必须处于一致状态。
  • 隔离性(Isolation):并发事务之间彼此隔离、独立,它不应以任何方式依赖于或影响其他事务。
  • 永久性(Durability):事务完成后,它对数据库的修改被永久保存。

事务分类

显式事务

  • 用BEGIN TRANSACTION明确指定事务的开始。
  • 最常用的事务类型。

隐性事务

  • 通过设置SETIMPLICIT_TRANSACTIONS ON语句,将隐性事务模式设置为打开。
  • 其后的T-SQL语句自动启动一个新事务。
  • 提交或回滚一个事务后,下一个T-SQL语句又将启动一个新事务。

自动提交事务

  • SQLServer的默认模式。
  • 每条单独的T-SQL语句视为一个事务。

如何创建事务

使用SQL语句管理事务的基本步骤

开始事务
  • BEGIN TRANSACTION
提交事务
  • COMMIT TRANSACTION
回滚(撤销)事务
  • ROLLBACK TRANSACTION

事务处理中的关键问题

  • 对事务中的insert、update、delete语句实时跟踪。

判断某条语句执行是否出错的方法

  • 使用全局变量@@ERROR
  • @@ERROR只判断当前一条T-SQL语句执行是否有错。
  • 为了判断事务中所有T-SQL语句是否有错,可以对错误进行累计。
SET@errorSum=@errorSum+@@ERROR

事务的应用

应用实践:编写存储讨程,实现学员一卡通转账功能,要求用户输入转入和转出的金额和账户

 测试转账存储过程

索引

索引类型

聚集索引(Clustered):表中各行的物理顺序与键值的逻辑(索引)顺序相同,每个表只能有一个

  • 主键索引:为表定义一个主键将自动创建主键索引,主键索引是唯一索引的特殊类型。
  • 主键索引要求主键中的每个值是唯一的,并且不能为空

非聚集索引(Non-clustered):非聚集索引指定表的逻辑顺序。

  • 数据存储在一个位置,索引存储在另一个位置,索引中包含指向数据存储位置的指针。
  • 可以有多个,小于249个
  • 唯一索引:唯一索引不允许两行具有相同的索引值

如何创建索引

 使用SQL Server Management Studio创建索引

使用SQL语句创建索引

 

 在Students表的StudentName列创建非聚集索引

按指定的索引查询数据

索引的优缺点

优点

  • 加快访问速度。
  • 加强行的唯一性。

缺点

  • 带索引的表在数据库中需要更多的存储空间。
  • 操纵数据的命令需要更长的处理时间,因为它们需要对索引进行更新。

创建索引的指导原则

按照下列标准选择建立索引的列

  • 频繁搜索的列。经常用作查询选择的列。
  • 经常排序、分组的列。
  • 经常用作联接的列(主键/外键)。

请不要使用下面的列创建索引

  • 仅包含几个不同值的列。
  • 表中仅包含几行。

使用索引时注意事项

  • 查询时减少使用*返回全部列,不要返回不需要的列
  • 索引应该尽量小,在字节数小的列上建立索引
  • WHERE子句中有多个条件表达式时,包含索引列的表达式应置于其他条件表达式之前
  • 根据业务数据发生频率,定期重新生成或重新组织索引,进行碎片整理

查看索引

ADO.NET的事务处理

ADO.NET提供了事务处理功能:

ADO.NET通过 SqlTransaction对象执行事务处理

使用ADO.NET事务

编写启用事务的通用数据访问方法

 

 

 

 测试ADO.NET事务(事务回滚)

 

 

 测试ADO.NET事务(事务提交)

 

 

 

 

示例

示例1:转账中遇到的问题

复制代码
 1 use StudentManager
 2 go
 3 --从贺小张的账户减掉1000
 4 update CardAccount set CurrentMoney=CurrentMoney-1000
 5            where StudentId=100001
 6 --给马小李的账户加上1000
 7 update CardAccount set CurrentMoney=CurrentMoney+1000
 8            where StudentId=100002
 9 --查询余额
10 select Students.StudentId,StudentName,CurrentMoney from Students
11 inner join CardAccount on Students.StudentId=CardAccount.StudentId
View Code
复制代码

示例2:使用事务回滚有错误的数据

复制代码
 1 use StudentManager
 2 go
 3 declare @errorSum int --定义变量,用于累计事务执行过程中的错误
 4 set @errorSum=0        --初始化为0,即无错误
 5 begin transaction
 6    begin                
 7     update CardAccount set CurrentMoney=CurrentMoney-1000
 8         where StudentId=100001
 9        set @errorSum=@errorSum+@@error --累计是否有错误                
10     update CardAccount set CurrentMoney=CurrentMoney+1000
11         where StudentId=100002
12       set @errorSum=@errorSum+@@error --累计是否有错误
13       if(@errorSum>0)
14     rollback transaction
15       else 
16           commit transaction
17  end
18 go
19 --查询余额
20 select Students.StudentId,StudentName,CurrentMoney from Students
21 inner join CardAccount on Students.StudentId=CardAccount.StudentId
View Code
复制代码

示例3:启用事务的转账存储过程

复制代码
 1 use StudentManager
 2 go
 3 if exists(select * from sysobjects where name='usp_TransferAccounts')
 4 drop procedure usp_TransferAccounts
 5 go
 6 create procedure usp_TransferAccounts
 7 @inputAccount int,--转入账户
 8 @outputAccount int,--转出账户
 9 @transferMoney int --交易金额
10 as
11     declare @errorSum int 
12     set @errorSum=0      
13     begin transaction
14        begin                
15         update CardAccount set CurrentMoney=CurrentMoney-@transferMoney
16             where StudentId=@outputAccount
17         set @errorSum=@errorSum+@@error         
18         update CardAccount set CurrentMoney=CurrentMoney+@transferMoney
19             where StudentId=@inputAccount
20            set @errorSum=@errorSum+@@error 
21            if(@errorSum>0)
22             rollback transaction
23            else 
24             commit transaction
25      end        
26 go
27 --测试失败的转账
28 exec usp_TransferAccounts 100002,100001,1000
29 --查询余额
30 select Students.StudentId,StudentName,CurrentMoney from Students
31 inner join CardAccount on Students.StudentId=CardAccount.StudentId
32 --测试成功的转账
33 exec usp_TransferAccounts 100002,100001,800
34 --查询余额
35 select Students.StudentId,StudentName,CurrentMoney from Students
36 inner join CardAccount on Students.StudentId=CardAccount.StudentId
View Code
复制代码

示例4:使用T-SQL创建索引

复制代码
 1 use StudentManager
 2 go
 3 /*--检测是否存在该索引(索引存放在系统表sysindexes中)--*/
 4 IF EXISTS (SELECT name FROM sysindexes
 5           WHERE name = 'IX_Student_StudentName')
 6 DROP INDEX Student.IX_Student_StudentName  --删除索引
 7 GO
 8 
 9 /*--学生姓名列创建非聚集索引:填充因子为30%--*/
10 CREATE NONCLUSTERED INDEX IX_Student_StudentName
11    ON Students(StudentName)
12        WITH FILLFACTOR = 30
13 GO
View Code
复制代码

示例5:使用索引查询数据

复制代码
1 use StudentManager
2 go
3 /*----指定按索引:IX_Student_StudentName查询----*/
4 SELECT * FROM Students
5 WITH (INDEX=IX_Student_StudentName)
6 WHERE StudentName LIKE '刘%'
View Code
复制代码

 

 

END

本文作者:云谷の风

本文链接:https://www.cnblogs.com/zeon/p/16324625.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   云谷の风  阅读(44)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开