断开连接的查询的TSQL事务行为 - 动态SQL

时间:2016-04-28 11:50:32

标签: sql-server tsql sql-server-2012 dynamic-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 个答案:

答案 0 :(得分:1)

是的,它可以工作,但您可能必须查看有多少存储过程以及回滚的影响。通常,您可以在存储过程中使用设置XACT_ABORT ON ,但由于动态SQL,它不会有任何影响..

关于如何包装proc

的示例演示
begin try
begin tran
exec usp_main
commit
end try
begin catch
rollback
end catch

我尝试使用XACT_ABORT进行了一些测试但是没有成功。但是当你发现任何错误时,将主进程包装在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