读书人

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

发布时间: 2012-09-15 19:09:29 作者: rapoo

存储过程中事务回滚的问题
有两张表,分别为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 

读书人网 >SQL Server

热点推荐