Sqlserver Sql Agent中的Job默认情况下只能有一个实例在运行,也就是说假如你的Sql Agent里面有一个正在运行的Job叫"Test Job",如果你现在再去启动一次"Test Job"就会报错,因为Sqlserver规定在一个Sqlserver账号下,Sql Agent不能同时启动相同的Job两次,只有前一次启动执行完成后,才能够再次启动该Job。
那么随之而来的问题是如何用sql语句检测Job是否已经执行完毕了呢?下面有一个语句可以作为参考:
Declare @Job_ID as UNIQUEIDENTIFIER select @Job_ID =Job_ID from msdb.dbo.sysjobs where name = ‘James_Test‘--name就是Job的名字 Exec master..sp_MSget_jobstate @Job_ID --返回值为 1 - 正在运行,4 - 表示完成(成功或失败)
以上语句的关键就是调用一个master库中的系统存储过程sp_MSget_jobstate,这个存储过程的结构可以从Sqlserver中查到如下,必要时可以建立一个自定义存储过程进行修改:
USE [master] GO /****** Object: StoredProcedure [sys].[sp_MSget_jobstate] Script Date: 2016/1/29 13:51:37 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- Procedure sp_MSget_jobstate -- -- Descriptions: -- The proc takes a specific Job ID and returns the Job State of the job -- Returns a row with one column job_state -- Returns a row with NULL if job does not exist -- -- Parameters: as defined in create statement -- -- Returns: 0 - success -- 1 - Otherwise -- -- Security: -- Requires Certificate signature for catalog access -- ALTER procedure [sys].[sp_MSget_jobstate] @job_id UNIQUEIDENTIFIER AS BEGIN DECLARE @is_sysadmin INT DECLARE @job_owner sysname DECLARE @job_state INT DECLARE @job_id_as_char VARCHAR(36) SET NOCOUNT ON CREATE TABLE #xp_results (job_id UNIQUEIDENTIFIER NOT NULL, last_run_date INT NOT NULL, last_run_time INT NOT NULL, next_run_date INT NOT NULL, next_run_time INT NOT NULL, next_run_schedule_id INT NOT NULL, requested_to_run INT NOT NULL, -- BOOL request_source INT NOT NULL, request_source_id sysname collate database_default null, running INT NOT NULL, -- BOOL current_step INT NOT NULL, current_retry_attempt INT NOT NULL, job_state INT NOT NULL) -- Need a job_id if (@job_id IS NULL) BEGIN SELECT @job_id_as_char = CONVERT(VARCHAR(36), @job_id) RAISERROR(14262, -1, -1, ‘@job_id‘, @job_id_as_char) RETURN(1) -- Failure END -- Capture job execution information (for local jobs only since that‘s all SQLServerAgent caches) SELECT @is_sysadmin = ISNULL(IS_SRVROLEMEMBER(N‘sysadmin‘), 0) SELECT @job_owner = suser_sname(suser_sid()) INSERT INTO #xp_results EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner -- Select the job state of the job in question SELECT @job_state = job_state FROM #xp_results WHERE @job_id = job_id -- Error if we have no rows selected if (@job_state IS NULL) BEGIN SELECT @job_id_as_char = CONVERT(VARCHAR(36), @job_id) RAISERROR(14262, -1, -1, ‘@job_id‘, @job_id_as_char) RETURN(1) -- Failure END ELSE SELECT @job_state -- All done DROP TABLE #xp_results RETURN(0) -- Success END
如果查询到Sql Agent中的Job正在执行,可以使用存储过程msdb.dbo.sp_stop_job强制停止Job,然后再使用存储过程msdb.dbo.sp_start_job来启动Job,需要注意的是如果在已经停止的Job上调用msdb.dbo.sp_stop_job或者在正在执行的Job上调用msdb.dbo.sp_start_job会报错,所以在调用存储过程msdb.dbo.sp_start_job和msdb.dbo.sp_stop_job前需要判断Job的当前执行状态,或者使用sql的Try Catch语句来捕获错误,msdb.dbo.sp_stop_job和msdb.dbo.sp_stop_job的使用方法如下所示:
EXEC msdb.dbo.sp_start_job @job_name=‘Job_name‘--Job_name就是Job的名字 EXEC msdb.dbo.sp_stop_job @job_name=‘Job_name‘--Job_name就是Job的名字
时间: 2024-10-13 11:22:43