我有以下存储过程,它动态调用存储过程列表。它已经存在了几个月并且运行良好(不幸的是我对服务器的访问非常有限,因此无法以其他方式管理)
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
我想要发生的事情是回滚交易 - 这会迎合这个吗?
答案 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