一直以来我都是在存储过程中使用事务

create proc usp_proc

begin

begin  tran

.....

commit

end

 

那么我现在问一个问题,如果在BCB的代码中写这样的代码

 

ADOConnection->BeginTrans();

ADOQuery->SQL->Text = "EXEC usp_proc ";

//ADOConnection->CommitTrans();  <---注意,我没有提交事务!

 

那么存储过程中的事务会提交吗?

 

答案是:NO

--------------------------------------------

那么现在来回答,为什么存储过程中的事务没有提交。

 

本质原因是因为:存储过程中的事务没有命名。

 

它只是简单的写了

BEGIN TRAN

 

COMMIT

 

于是问题就来,当BCB启动了一个事务的时候,

执行存储过程 到COMMIT 处,SQL SERVER 到底是提交 BCB代码中 BeginTrans 开启的事务呢,还是 存储过程中的事务呢?

因为没有显示的指定要提交哪一个事务,所以,SQL SERVER 就提交“上一个”;(类似计数器风格)

因为BCB 代码中的事务是先开始的,所以SQL SERVER 提交的是 BCB代码中的事务。也就是说,存储过程中的事务并没有提交。

那么,假设你的存储过程中有一个 TABLOCKX ,会怎样,全部都会阻塞。

 

总结一句话,COMMIT 这样的代码,是让SQL SERVER 简单的提交上一个事务而已。

换句话说,你可以这么写代码(如果你真的这么写,被开除了不要怪我)

 

BCB中

ADOConnectin->BeginTrans();

 

然后执行存储过程。

存储过程中这么写

create proc usp_proc

as

begin

   。。。。do sth

  commit;  <---直接写一个commit,它就会提交BCB代码中的事务。

end

 

那么如何保证存储过程中的事务提交呢?

 

答案是给事务命名

 

具体的写法看MSDN 的例子,这样,即使BCB得事务没有提交,SQL SERVER 也一定会提交存储过程中的事务的。

 

DECLARE @TranName VARCHAR(20);
SELECT @TranName = 'MyTransaction';

BEGIN TRANSACTION @TranName;
USE AdventureWorks2008R2;
DELETE FROM AdventureWorks2008R2.HumanResources.JobCandidate
    WHERE JobCandidateID = 13;

COMMIT TRANSACTION @TranName;
GO

 

再谈谈BCB中能不呢个对事务进行命名。答案是:NO

 

再来谈谈事务和会话的关系,一个会话可以有多个事务,比如 先执行事务A,再执行事务B,再提交事务A,然后提交事务B ,

这其实是事务嵌套,B事务嵌套到A事务中了。

用一个ADOConnection 做不到,只能借助存储过程来做。切记,BCB的ADOConnection 只能开启一个事务。

 

posted on 2016-09-19 13:45  zooz  阅读(1042)  评论(0编辑  收藏  举报