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.

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>

Comments

  1. Thx a ton for this! I have this employed, and now my cf is kicking off an SSIS pkg! Too cool.

    -Steve

    ReplyDelete

Post a Comment

Popular posts from this blog

ColdFusion in an Enterprise Environment - Part 1 - Understanding how to use SubVersion (SVN)

coldfusion builder 2 extension not displaying browse button on type=projectdir

Being Thread Safe in Coldbox/Coldfusion