Coding MSSQL Start Job and Wait for it
I've been kicking off SQL Agent Jobs for a long time now, but I've never needed to wait for it to end before. Until today, I needed to pull data from a Ultra Secure SQL Server database and didn't want my web servers to have access to the ultra secure sql server. So I decided to create command line SQL Scripts that connected to the secure database and pull data into a "staging" table. And use a Sql Agent job to run that script. But using the following SQL kicked off the job, but didn't wait until it was finished.
Therefore, I needed a Query that let me know if the job was still running. The following query checks the activity table to see if one is running and hasn't finished yet, returning job name if it is still running.
Using this query in a loop until no records are returned gives the "wait" concept.
Lastly, we want to make sure the job finished successfully. The following query access the history portion of the job, which is all executions not just the last one. Therefore, we want to only look at the job (not steps, step_id = 0), and make sure it ran today, and grab the latest (order by with top 1)
In ColdFusion the following code is how I implemented the entire concept.
msdb..sp_start_job @job_name = '<job name>'
Therefore, I needed a Query that let me know if the job was still running. The following query checks the activity table to see if one is running and hasn't finished yet, returning job name if it is still running.
select j.[name]
from
msdb..sysjobs j
inner join msdb..sysjobactivity a on a.job_id = j.job_id
where
j.name = '<job name>'
AND a.start_execution_date is not null
AND a.job_history_id is null
Using this query in a loop until no records are returned gives the "wait" concept.
Lastly, we want to make sure the job finished successfully. The following query access the history portion of the job, which is all executions not just the last one. Therefore, we want to only look at the job (not steps, step_id = 0), and make sure it ran today, and grab the latest (order by with top 1)
select top 1 *
from
msdb..sysjobs j
inner join msdb..sysjobhistory h on h.job_id = j.job_id
where
j.name = '<job name>'
and h.step_id = 0
and h.run_date = convert(varchar(8),getDate(),112)
order by
h.run_date desc,
h.run_time desc
In ColdFusion the following code is how I implemented the entire concept.
<cfquery name="ZipCodeStagingLoad" datasource="sealprod_staging">
msdb..sp_start_job @job_name = 'ZipCode Load'
</cfquery>
<cfset thread = CreateObject("java", "java.lang.Thread")>
<cfset hold = 0 />
<cfloop condition="hold eq 0">
<cfquery name="check" datasource="sealprod_staging">
select j.[name]
from
msdb..sysjobs j
inner join msdb..sysjobactivity a on a.job_id = j.job_id
where
j.name = 'ZipCode Load'
AND a.start_execution_date is not null
AND a.job_history_id is null
</cfquery>
<cfif check.recordCount eq 1>
<!--- STILL RUNNING IF RECORD IS RETURNED --->
<cfset thread.sleep(5000)>
<cfelse>
<cfset hold = 1 />
</cfif>
</cfloop>
<cfquery name="checkStatus" datasource="sealprod_staging">
select top 1 h.run_status, h.message
from
msdb..sysjobs j
inner join msdb..sysjobhistory h on h.job_id = j.job_id
where
j.name = 'ZipCode Load'
and h.step_id = 0
and h.run_date = convert(varchar(8),getDate(),112)
order by
h.run_date desc,
h.run_time desc
</cfquery>
<cfif checkStatus.run_status EQ 0>
<cfthrow type="SQL.AGENT" errorcode="1" message="SQL AGENT JOB Failed" detail="#checkStatus.message#" />
</cfif>
Thx a ton for this! I have this employed, and now my cf is kicking off an SSIS pkg! Too cool.
ReplyDelete-Steve