[置顶] 【机房重构】——存储过程+事务

    有过第一版的机房收费系统,大家都很清楚知道有些调用数据库表的操作真的是很麻烦,就用机房收费系统中的注册,既要更新学生表,卡表,还需要更新充值记录表,三张表的操作,除了它在代码的编写过程很麻烦,耦合性很高,还有一点就是在这个过程很有可能更新其中的一张表后,就报错了,这样的结果就是数据库中的数据不再统一。同样的问题,如果应用到银行存款,后果不堪设想啊。。。

问题

    首先分析上面的问题,一是多张表的同时操作,比较麻烦;二是如果数据过程中出错,会造成整个系统中的数据不一致。遇到问题一个个的解决。

存储过程

    不知道大家在学习数据库的时候是否注意到存储过程这个东西,学习是一个不断进步的过程。因为数据库用的比较少,所以这一次果断使用存储过程完成这个更新过程。先让我们温故一下:

存储过程的定义:一组为了完成特定功能的SQL语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程。

由此可见存储过程还是一个比较重要的部分吧。那么如何使用呢?首先存储过程位于什么位置?

              [置顶] 【机房重构】——存储过程+事务_第1张图片

我第一次用存储过程是在学生的注册部分,这种东西其实看看就很能搞懂的。

ALTER PROCEDURE [dbo].[PROC_RegisterCard]
	@cardno varchar(50),
	@studentno varchar(50),
	@studentName varchar(50),
	@Cash varchar(50),
	@sex varchar(50),
	@department varchar(50),
	@grade varchar(50),
	@class varchar(50),
	@explain varchar(500),
	@UserID varchar(10),
	@style varchar(10),
	@RegisterDate varchar(50),
	@RegisterTime varchar(50),
	@CheckCash varchar(50)
AS
begin 
	
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	--SET NOCOUNT ON;
	--SET XACT_ABORT ON; 
	
    -- Insert statements for procedure here
	--在表card_Info 中添加卡号
	insert into Card_Info values(@cardno ,@studentno ,@RegisterDate ,@RegisterTime ,@UserID ,@Cash ,@style )
	
	insert into Student_Info values(@studentno ,@studentName ,@sex,@department ,@grade ,@class ,@explain )
  
	insert into ReCharge_Info (cardno,AddMoney ,Date ,Time ,UserID ,CheckCash )values (@cardno ,@cash,@RegisterDate ,@RegisterTime ,@UserID ,@CheckCash )
	
    END

这样就能帮助我们提高编写的效率,更是能提高系统的性能。但是第二个问题依旧存在,如何让它们要不同时执行,要不都不执行呢?是否还记的数据库中的事务?

事务

事务的四个特性,成为我们钟爱的原因。

1、原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。

2、一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

3、隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

4、持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

这一次我们主要使用它的原子性,下面是具体的代码,主要是在原来代码的基础上添加事务回滚。

ALTER PROCEDURE [dbo].[PROC_RegisterCard]
	@cardno varchar(50),
	@studentno varchar(50),
	@studentName varchar(50),
	@Cash varchar(50),
	@sex varchar(50),
	@department varchar(50),
	@grade varchar(50),
	@class varchar(50),
	@explain varchar(500),
	@UserID varchar(10),
	@style varchar(10),
	@RegisterDate varchar(50),
	@RegisterTime varchar(50),
	@CheckCash varchar(50)
AS
begin 
	declare @error int 
	set @error=0
    BEGIN transaction
	
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	--SET NOCOUNT ON;
	--SET XACT_ABORT ON; 
	
    -- Insert statements for procedure here
	--在表card_Info 中添加卡号
	insert into Card_Info values(@cardno ,@studentno ,@RegisterDate ,@RegisterTime ,@UserID ,@Cash ,@style )
	set @error=@error+@@error 
	--save tran bcd  --保存一个事务点
	--在表student_Info 中添加学生信息
	insert into Student_Info values(@studentno ,@studentName ,@sex,@department ,@grade ,@class ,@explain )
    set @error =@error +@@error 
	--增添表ReCharge_Info表中的充值记录
	insert into ReCharge_Info (cardno,AddMoney ,Date ,Time ,UserID ,CheckCash )values (@cardno ,@cash,@RegisterDate ,@RegisterTime ,@UserID ,@CheckCash )
	set @error=@error+@@error
	if @error<>0 
		rollback transaction --如果不等于0,则回滚事务,不能执行
	else 
		commit transaction --等于0,则执行该事务
    END

所以机房中的注册过程,通过存储过程+事务完美解决。虽然这些东西很好,但是过分的依赖同样要有大麻烦。

缺点

    1:移植问题,数据库端代码当然是与数据库相关的。但是如果是做工程型项目,基本不存在移植问题。

    2:重新编译问题,因为后端代码是运行前编译的,如果带有引用关系的对象发生改变时,受影响的存储过程、包将需要重新编译(不过也可以设置成运行时刻自动编译)。

    3: 如果在一个程序系统中大量的使用存储过程,到程序交付使用的时候随着用户需求的增加会导致数据结构的变化,接着就是系统的相关问题了,最后如果用户想维护该系统可以说是很难很难、而且代价是空前的,维护起来更麻烦。

【总结】

    存储过程和事务,尽管在数据库学习的时候了解过,但是相对于之前的自己确实是很陌生的东西,所以尝试使用是我们面对陌生的最好办法。在使用的过程中渐渐熟悉,这对我们自己更是一种挑战,然而这些挑战都将帮助我们变得越来越好,所以既然花费的大量的时间和尽力来做这件事,就尽可能的让自己多多成长些!

 

你可能感兴趣的:([置顶] 【机房重构】——存储过程+事务)