首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

存储过程中事务回滚的有关问题

2012-09-15 
存储过程中事务回滚的问题有两张表,分别为Table1(结构:COLA1 nvarchar(10) null,COLA2 nvarchar(10) null)

存储过程中事务回滚的问题
有两张表,分别为Table1(结构:COLA1 nvarchar(10) null,COLA2 nvarchar(10) null) 和Table2(结构:COLB1 nvarchar(10) not null,COLB2 nvarchar(10) null),向两张表中用INSERT INTO写入数据,用事务处理,如果有一张表写入不成功,则两张表的数据都不写入。
我写了一个存储过程:
[code=SQL][/code]
CREATE PROCEDURE Sp_CU_Test(
  @AA1 nvarchar(10),
  @AA2 nvarchar(10),
  @BB1 nvarchar(10),
  @BB2 nvarchar(10)
)
AS
DECLARE @cSqlString1 nvarchar(4000)
DECLARE @cSqlString2 nvarchar(4000)
BEGIN TRAN
SET @cSqlString1 ='INSERT INTO Table1(COLA1,COLA2) VALUES('''+@AA1+''' ,'''+@AA2+''')'
SET @cSqlString2 ='INSERT INTO Table2(COLB1,COLB2) VALUES('''+@BB1+''' ,'''+@BB2+''')'
exec(@cSqlString1+' '+ @cSqlstring2)
if @@ERROR <>0
  begin
  rollback tran
  end
else
  commit tran  
Go  

结果:测试 EXEC Sp_CU_Test 'AA1','AA1',NULL,'BB1'
  结果:Table1中写入了记录,Table2中没有写入记录。(要求是如果有一张表写入数据不成功则回滚,而测试结果是Table1写入了记录,Table2没有写入记录)

另外做了一个测试的存储过程:
CREATE PROCEDURE Sp_CU_Test(
  @AA1 nvarchar(10),
  @AA2 nvarchar(10),
  @BB1 nvarchar(10),
  @BB2 nvarchar(10)
)
AS
DECLARE @cSqlString1 nvarchar(4000)
DECLARE @cSqlString2 nvarchar(4000)
BEGIN TRAN
--SET @cSqlString1 ='INSERT INTO Table1(COLA1,COLA2) VALUES('''+@AA1+''' ,'''+@AA2+''')'
--SET @cSqlString2 ='INSERT INTO Table2(COLB1,COLB2) VALUES('''+@BB1+''' ,'''+@BB2+''')'
--exec(@cSqlString1+' '+ @cSqlstring2)
INSERT INTO TABLE1(COLA1,COLA2) VALUES(@AA1,@AA2 )
INSERT INTO TABLE2(COLB1,COLB2) VALUES(@BB1,@BB2 )

if @@ERROR <>0
  begin
  rollback tran
  end
else
  commit tran  
Go  

测试结果:EXEC Sp_CU_Test 'AA1','AA2',NULL,'BB1'
  在Table1和Table2中都没有写入数据(写Table1的语句可以写入记录,写Table2的语句由于COLB1的值是不允许为NULL,所以不可以写入记录,最后回滚以后,两张表都记录)

问题:1、这两个存储过程看上去差不多,为什么结果会不一样呢?
  2、第一个存储过程要怎么样修改才能实现第二个存储过程那样的效果?

[解决办法]
动态语句如下实现

SQL code
CREATE PROCEDURE Sp_CU_Test(  @AA1 nvarchar(10),  @AA2 nvarchar(10),  @BB1 nvarchar(10),  @BB2 nvarchar(10))ASDECLARE @cSqlString1 nvarchar(4000)DECLARE @cSqlString2 nvarchar(4000)SET @cSqlString1 ='INSERT INTO Table1(COLA1,COLA2) VALUES('''+@AA1+''' ,'''+@AA2+''')'SET @cSqlString2 ='INSERT INTO Table2(COLB1,COLB2) VALUES('''+@BB1+''' ,'''+@BB2+''')'DECLARE @SQL NVARCHAR(400)SET @SQL = N'SET XACT_ABORT ONBEGIN TRAN' + @cSqlString1 + '' + @cSqlString2 + 'commit tran'exec(@SQL)Go
[解决办法]
SQL code
SET @cSqlString1 ='INSERT INTO Table1(COLA1,COLA2) VALUES('''+@AA1+''' ,'''+@AA2+''')'SET @cSqlString2 ='INSERT INTO Table2(COLB1,COLB2) VALUES('''+@BB1+''' ,'''+@BB2+''')'DECLARE @SQL NVARCHAR(8000)--2005/2008BEGIN TRYBEGIN TRAN    exec(@cSqlString1+' '+ @cSqlstring2)    IF (XACT_STATE()) = 1    COMMIT TRANEND TRYBEGIN CATCH    IF (XACT_STATE()) != 1    ROLLBACK TRAN    SELECT        ERROR_NUMBER() AS ErrorNumber        ,ERROR_SEVERITY() AS ErrorSeverity        ,ERROR_STATE() AS ErrorState        ,ERROR_PROCEDURE() AS ErrorProcedure        ,ERROR_LINE() AS ErrorLine        ,ERROR_MESSAGE() AS ErrorMessage;END CATCH
[解决办法]
SQL code
CREATE PROCEDURE Sp_CU_Test( @AA1 nvarchar(10),  @AA2 nvarchar(10),  @BB1 nvarchar(10),  @BB2 nvarchar(10))ASDECLARE @cSqlString1 nvarchar(4000)DECLARE @cSqlString2 nvarchar(4000)SET @cSqlString1 ='INSERT INTO Table1(COLA1,COLA2) VALUES('''+@AA1+''' ,'''+@AA2+''')'SET @cSqlString2 ='INSERT INTO Table2(COLB1,COLB2) VALUES('''+@BB1+''' ,'''+@BB2+''')'set xact_abort onBEGIN TRANexec(@cSqlString1)exec(@cSqlstring2)commit tran   Go 

热点排行