2016-04-28 71 views
0

我有下面的存儲過程,動態調用存儲過程的列表。它沿用了數個月,一直運行良好(不幸的是我的服務器是相當限制,訪問不能管理這個任何其他方式)TSQL事務行爲與斷開連接的查詢 - 動態SQL

Alter Proc [Process].[UspLoad_LoadController] 
(
    @HoursBetweenEachRun Int 
) 
As 
Begin 
--find all procedures that need to be updated 
    Create Table [#ProcsToRun] 
     (
      [PID] Int Identity(1 , 1) 
     , [SchemaName] Varchar(150) 
     , [ProcName] Varchar(150) 
     ); 

    Insert [#ProcsToRun] 
      ([SchemaName] 
      , [ProcName] 
      ) 
      Select [s].[name] 
        , [p].[name] 
      From [sys].[procedures] [p] 
        Left Join [sys].[schemas] [s] 
         On [s].[schema_id] = [p].[schema_id] 
      Where [s].[name] = 'Process' 
        And [p].[name] Like 'UspUpdate%'; 

    Declare @MaxProcs Int 
     , @CurrentProc Int = 1; 

    Select @MaxProcs = Max([PID]) 
    From [#ProcsToRun]; 

    Declare @SQL Varchar(Max) 
     , @SchemaName sysname 
     , @ProcName sysname; 

--run through each procedure, not caring if the count changes and only updating if there have been more than 23 hours since the last run 
    While @CurrentProc <= @MaxProcs 
     Begin 
      Select @SchemaName = [SchemaName] 
        , @ProcName = [ProcName] 
      From [#ProcsToRun] 
      Where [PID] = @CurrentProc; 

      Select @SQL = @SchemaName + '.' + @ProcName 
        + ' @PrevCheck = 0,@HoursBetweenUpdates = ' 
        + Cast(@HoursBetweenEachRun As Varchar(5)); 

      Exec (@SQL); 
      Set @CurrentProc = @CurrentProc + 1; 
     End; 
End; 
Go 

然而,環境這是在運行偶爾遭受來自通信錯誤,查詢在執行過程中被取消。

我的問題是 - 我可以用事務語句包裝整個過程,並且如果我可以在查詢被提前終止的情況下發生什麼?

BEGIN Tran Test 
Exec [Process].[UspLoad_LoadController] @HoursBetweenEachRun = 1; 
COMMIT TRANSACTION Test 

我想要發生的事情將是事務回滾 - 這會迎合這一點嗎?

回答

1

是它的工作原理,但你可能要看看你有多少存儲的特效已經和rollback.Normally的影響,你可以使用設置XACT_ABORT ON存儲過程裏面,但由於動態SQL,它不會有任何效果。 。如何包裝你的PROC

樣品演示

begin try 
begin tran 
exec usp_main 
commit 
end try 
begin catch 
rollback 
end catch 

一些測試,我做了嘗試使用XACT_ABORT與任何success.but包裹你的主要PROC在Tran和當發生任何錯誤回滾,回滾所有存儲的特效。

create table test2 
(
id int) 

create table test3 
(
id int) 



create proc usp_test2 
as 
begin 
insert into test2 
select 1 
end 


alter proc usp_test3 
as 
begin 
insert into test3 
select 1/0 
end 


alter proc usp_main 
as 
begin 
set xact_abort on 
declare @sql1 nvarchar(2000) 
set @sql1='exec usp_test2' 

declare @sql2 nvarchar(2000) 
set @sql2='exec usp_test3' 

exec (@sql1) 
exec(@sql2) 
end