首先去執行一個stored procedure(sp_Test1),而sp_Test1有個transaction 裡面要執行另外兩個stored procedure(sp_Test2、sp_Test3),然後如果進到catch則rollback transaction,另外還有個output parameter用來傳回sp_Test2新增的Id值,SQL語法如下
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CREATE PROCEDURE [dbo].[sp_Test1] | |
@table1_Id INT OUTPUT | |
AS | |
begin try | |
begin transaction | |
print 'sp_Test1:executing sp_Test2' | |
exec sp_Test2 @table1_Id output | |
print 'sp_Test1:executing sp_Test3' | |
exec sp_Test3 | |
print 'commit tran' | |
commit transaction | |
end try | |
begin catch | |
rollback transaction | |
print 'sp_Test1:in catch' | |
RAISERROR('raiseerror:sp_Test1', 16, 1) | |
end catch |
sp_Test2: insert資料到testTable1並傳回IDENTITY值,傳回的值在sp_Test1有@table1_Id參數會output回去
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CREATE PROCEDURE [dbo].[sp_Test2] | |
@table1_Id INT OUTPUT | |
AS | |
print 'sp_Test2:insert' | |
insert into testTable1 values('col1') | |
select @table1_Id = @@IDENTITY |
sp_Test3: update testTable2的Num欄位值為6,但testTable2有個trigger (NumTrigger),當update時會去判斷如果新的Num>5就RAISERROR並rollback
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CREATE PROCEDURE [dbo].[sp_Test3] | |
AS | |
begin try | |
print 'sp_Test3:updating' | |
update testTable2 set Num=6 where Id=2 | |
print 'sp_Test3:updated' | |
end try | |
begin catch | |
print 'sp_Test3:in catch' | |
RAISERROR('raiseerror:sp_Test3', 16, 1) | |
end catch |
testTable1的schema
testTable2的schema
新增一筆資料讓testTable有資料可以做update
NumTrigger主要判斷如果新增的num>5就RAISERROR
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CREATE TRIGGER [dbo].[NumTrigger] | |
ON [dbo].[testTable] | |
FOR UPDATE | |
AS | |
BEGIN | |
print 'begin trigger' | |
if UPDATE(Num) | |
BEGIN | |
DECLARE @num int | |
select @num=Num from inserted | |
print 'inserted num:' + cast(@num as nvarchar) | |
if @num>5 | |
BEGIN | |
print 'raiseerror in trigger' | |
RAISERROR('Error:Trigger', 16, 2) | |
rollback | |
End | |
End | |
END |
所以這裡想驗證的是
1.如果在trigger中發生error,那sp_Test1應該會進到catch裡去rollback transaction?(就理論上來說應該要會)
2.如果rollback了那output 參數table1_Id回傳的值是?
測試用的資料庫我就直接拿一個之前已經放在Azure上的測試DB用,然後執行如下圖的指令
執行結果如下
從結果可以看出在sp_Test3做update時因為觸發trigger沒過丟回error進到catch,然後catch裡RAISERROR則回到sp_Test1的catch,所以rollback transaction,整個流程跟理論上的認知是一樣沒錯的。
而另外原本先做了insert回傳的table1_Id值(auto increment)則是跟rollback前一樣(範例中上個seed到7),但去查詢table並沒有資料被加入,也就是說insert的資料被rollback但auto increment的seed不會跟著復原,所以當下次新增一筆資料到table1時,ID值就會為9了
0 意見:
張貼留言