假设以下 SQL Server 代理作业
USE [msdb]
GO
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
END
DECLARE @jobId BINARY(16)
EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'Do Nothing',
@enabled=1,
@notify_level_eventlog=0,
@notify_level_email=0,
@notify_level_netsend=0,
@notify_level_page=0,
@delete_level=0,
@description=N'No description available.',
@category_name=N'[Uncategorized (Local)]',
@owner_login_name=N'Me', @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'Wait',
@step_id=1,
@cmdexec_success_code=0,
@on_success_action=1,
@on_success_step_id=0,
@on_fail_action=2,
@on_fail_step_id=0,
@retry_attempts=0,
@retry_interval=0,
@os_run_priority=0, @subsystem=N'TSQL',
@command=N'WAITFOR DELAY ''00:00:10''',
@database_name=N'master',
@flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:
GO
以及以下调用代码
EXEC msdb.dbo.sp_start_job @job_name = 'Do nothing' -- waits for 10 seconds
WAITFOR DELAY '00:00:05'
EXEC msdb.dbo.sp_start_job @job_name = 'Do nothing' -- fails, job still running
WAITFOR DELAY '00:00:10'
EXEC msdb.dbo.sp_start_job @job_name = 'Do nothing' -- should succeed
我收到以下错误:
Job 'Do nothing' started successfully. Msg 22022, Level 16, State 1, Line 25 SQLServerAgent Error: Request to run job Do Nothing (from User Me) refused because the job is already running from a request by User Me. Job 'Do nothing' started successfully.
因此我们可以看到第二次sp_start_job
调用失败,因为作业仍在运行,然后 SQL Server 继续执行
故障级别为 16,当我执行以下操作时
PRINT 'hello'
RAISERROR ('error',16,1)
PRINT 'hello'
我得到了相同的“失败并继续”行为
hello
Msg 50000, Level 16, State 1, Line 50
error
hello
但是,如果我执行以下操作,也会引发 16 级错误,则不会运行第二次打印
PRINT 'hello'
;THROW 51000, 'error', 1;
PRINT 'hello'
hello
Msg 51000, Level 16, State 1, Line 50
error
THROW状态的文档
THROW 语句中发生的任何错误都会导致语句批处理终止。
RAISERROR状态的文档
如果运行 RAISERROR,则会将错误返回给调用者:超出任何 TRY 块的范围。在 TRY 块中严重性为 10 或更低。严重性为 20 或更高,终止数据库连接。
我的问题是,是否sp_start_job
使用 RAISERROR 而不是 throw - 我已经研究过定义,但找不到任何地方
是的,它确实使用了
RAISERROR
,至少在我能看到的代码部分是这样。还有一些内部使用的扩展程序,我们没有这些程序的源代码,但我怀疑这里也会这样。您应该使用
BEGIN CATCH
来捕获此类错误,因为即使是 也RAISERROR
不会终止执行。SET XACT_ABORT
ON
以下是 的完整定义
sp_start_job
,您可以看到它RAISERROR
在很多地方使用。您可以使用 获得此定义select definition from msdb.sys.sql_modules where object_id = object_id('msdb..sp_start_job')
。