tho*_*der 4 sql-server sql-server-agent try-catch
我sp_start_job用来开始工作.
job(test2)只有一步:
select getdate()
waitfor delay '00:00:10'
Run Code Online (Sandbox Code Playgroud)
该TRY/CATCH代码:
begin try
EXEC msdb.dbo.sp_start_job @job_name = 'test2'
end try
begin catch
print 'error'
end catch
Run Code Online (Sandbox Code Playgroud)
首次运行代码:
Job'test2'成功启动.
第二次运行代码(10秒内):
消息22022,级别16,状态1,行0
SQLServerAgent错误:请求运行作业test2(来自用户sa)被拒绝,因为作业已经从用户sa的请求运行.
为什么TRY/CATCH在这种情况下不起作用?
更新:我应该首先添加我正在使用链接服务器(sql server 2000)的sql server 2005.我试图在sql server 2005服务器上编写一个proc来查看所有链接服务器上的作业.如果作业未运行,请运行它.最初,我使用try-catch并希望在运行已经运行的作业时捕获任何错误但是失败了(这个线程).
我终于使用了以下代码:(它不会编译,你需要替换一些变量,只是给出一个想法)
CREATE TABLE [dbo].[#jobInfo](
[job_id] [uniqueidentifier] NULL,
[originating_server] [nvarchar](30) ,
[name] [nvarchar](128) ,
[enabled] [tinyint] NULL,
[description] [nvarchar](512) ,
[start_step_id] [int] NULL,
[category] [nvarchar](128) ,
[owner] [nvarchar](128) ,
[notify_level_eventlog] [int] NULL,
[notify_level_email] [int] NULL,
[notify_level_netsend] [int] NULL,
[notify_level_page] [int] NULL,
[notify_email_operator] [nvarchar](128) ,
[notify_netsend_operator] [nvarchar](128) ,
[notify_page_operator] [nvarchar](128) ,
[delete_level] [int] NULL,
[date_created] [datetime] NULL,
[date_modified] [datetime] NULL,
[version_number] [int] NULL,
[last_run_date] [int] NOT NULL,
[last_run_time] [int] NOT NULL,
[last_run_outcome] [int] NOT NULL,
[next_run_date] [int] NOT NULL,
[next_run_time] [int] NOT NULL,
[next_run_schedule_id] [int] NOT NULL,
[current_execution_status] [int] NOT NULL,
[current_execution_step] [nvarchar](128) ,
[current_retry_attempt] [int] NOT NULL,
[has_step] [int] NULL,
[has_schedule] [int] NULL,
[has_target] [int] NULL,
[type] [int] NOT NULL
)
SET @sql =
'INSERT INTO #jobInfo
SELECT * FROM OPENQUERY( [' + @srvName + '],''set fmtonly off exec msdb.dbo.sp_help_job'')'
EXEC(@sql)
IF EXISTS (select * from #jobInfo WHERE [name] = @jobName AND current_execution_status IN (4,5)) -- 4: idle, 5: suspended
BEGIN
SET @sql = 'EXEC [' + @srvName + '].msdb.dbo.sp_start_job @job_name = ''' + @jobName + ''''
--print @sql
EXEC (@sql)
INSERT INTO #result (srvName ,status ) VALUES (@srvName, 'Job started.')
END ELSE BEGIN
INSERT INTO #result (srvName ,status ) VALUES (@srvName, 'Job is running already. No action taken.')
END
Run Code Online (Sandbox Code Playgroud)
并非所有错误都可以被捕获TRY/CATCH.在这种情况下,sp_start_job实际上调用外部过程,这些超出了SQL Server的错误处理范围.或者至少那是他们坚持的故事:
http://connect.microsoft.com/SQLServer/feedback/details/362112/sp-start-job-error-handling
另请注意,这仍是SQL Server 2012 SP1 CU3中的问题.如果您想修复此错误,请投票和评论.
一个繁琐但可行的解决方法,需要某些权限,在这种情况下假定作业所有者是sa:
DECLARE @x TABLE
(
a VARBINARY(32),b INT,c INT,d INT,e INT,f INT,g INT,h INT,i NVARCHAR(64),
Running BIT, -- the only important column
k INT,l INT,m INT
);
DECLARE @job_id UNIQUEIDENTIFIER;
SELECT @job_id = job_id FROM msdb.dbo.sysjobs WHERE name = N'test2';
INSERT @x EXEC master.dbo.xp_sqlagent_enum_jobs 1, N'sa', @job_id;
IF EXISTS (SELECT 1 FROM @x WHERE Running = 0)
BEGIN
EXEC msdb.dbo.sp_start_job @job_name = N'test2';
END
ELSE
BEGIN
PRINT 'error';
END
Run Code Online (Sandbox Code Playgroud)
更好的可能是:
DECLARE @job_id UNIQUEIDENTIFIER, @d DATETIME;
SELECT @job_id = job_id FROM msdb.dbo.sysjobs WHERE name = N'test2';
SELECT @d = stop_execution_date
FROM msdb.dbo.sysjobactivity WHERE job_id = @job_id;
IF @d IS NOT NULL
BEGIN
EXEC msdb.dbo.sp_start_job @job_name = N'test2';
END
ELSE
BEGIN
PRINT 'error';
END
Run Code Online (Sandbox Code Playgroud)
在任何一种情况下,仍然可能在检查其状态和启动它的调用之间开始作业,因此这并不能sp_start_job完全消除错误,但这使得它们不太可能发生.