【问题标题】:TSQL Transaction behaviour with disconnected queries - dynamic SQL断开查询的 TSQL 事务行为 - 动态 SQL
【发布时间】:2016-08-23 04:01:04
【问题描述】:

我有以下存储过程,它动态调用存储过程列表。它已经存在了几个月并且运行良好(不幸的是,我对服务器的访问受到很大限制,因此无法以任何其他方式进行管理)

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

我想要回滚事务 - 这会满足这个要求吗?

【问题讨论】:

    标签: sql-server tsql sql-server-2012 dynamic-sql


    【解决方案1】:

    是的,它有效,但您可能需要查看您拥有多少存储过程以及回滚的影响。通常您可以在存储过程中使用 Set XACT_ABORT ON,但由于动态 SQL,它不会有什么效果..

    关于如何包装你的过程的示例演示

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

    我在尝试使用 XACT_ABORT 时进行了一些测试,但没有成功。但是将主 proc 包装在 tran 中并在发生任何错误时回滚,也回滚所有存储的 proc。

    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 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 2015-11-19
      • 2017-05-17
      相关资源
      最近更新 更多