2016-04-28 49 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