存储过程中事务回滚的问题
有两张表,分别为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、第一个存储过程要怎么样修改才能实现第二个存储过程那样的效果?
[解决办法]
动态语句如下实现
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
[解决办法]
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
[解决办法]
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