Professional Documents
Culture Documents
Problem Definition
Like most DBAs, I have a lot of predictable maintenance tasks that Im required to monitor. For example, there are changes, specifically data loads, which happen on a 'quarterly' basis, as defined by the institution where I am employed. In this article I will describe an SSIS Package, that I have created, that once created into a job and run the first time, will schedule its next run before it completes.
Package Image
The red boxes with numbers correspond to the described Package Steps below.
Package Steps
This section describes the above image of an SSIS package and the details that are necessary to understand what is happening in each step.
Package Variables
Name Scope DataType
Scope Package Level Package Level Package Level Package Level Package Level Package Level
*Note that good practice calls for a naming standard to name variables; for example the variables should have str before the strings, and int before the integer variable.
Step Details
select Substring(Convert(varchar(30), qtrStartDate, 112),1,8) from CCSSM_REP.dbo.Quarter_Metadata where qtrIndex = (select qtrIndex+1 from CCSSM_REP.dbo.Quarter_Metadata where qtrCurrentQtr = 1)
As I am only showing a part of a single quarters information as an example, assume past and future quarter information exists. The T-SQL code grabs the next lines qtrStartDate, that exist in the table following the current quarter per the qtrCurrentQtr column. All that is needed is a valid future date SQL statement that returns the next date you want to run the job. For example, this SQL could easily be replaced with SQL that gives you the next Sunday date so that it handles weekly loads.
Step Details
*Step Images that involve scripting have associated images to show the package variables used.
Script Details
This step sets the package variables. This is where youll make your changes to fit your job name and schedule name. Also the date generating SQL (strSQL) will need to be modified to fit your needs. The key variable details are strSQL, JobName, and ScheduleName.
public void Main() { String strSQL ="select Substring(Convert(varchar(30), qtrStartDate, 112),1,8) from CCSSM_REP.dbo.Quarter_Metadata where qtrIndex = (select qtrIndex+1 from CCSSM_REP.dbo.Quarter_Metadata where qtrCurrentQtr = 1)"; Dts.Variables["strSQL"].Value = strSQL; Dts.Variables["JobName"].Value = "EdPlan_Fill_Extended_Info"; Dts.Variables["ScheduleName"].Value = "Quarterly_Run_Edplan_Fill_ExtendedInfo"; Dts.TaskResult = (int)ScriptResults.Success; }
Step Details
Result Set
Result Name 0 Variable Name User::ScheduleDate
Step Details
Script Details
public void Main() { // Get next Run date. String strSQL = "SELECT COUNT(*) FROM msdb.dbo.sysschedules where name ='" + Dts.Variables["ScheduleName"].Value + "'"; Dts.Variables["strSQL"].Value = strSQL; Dts.TaskResult = (int)ScriptResults.Success; }
Result Set
Result Name 0
Success Connectors
On the out-flow of this Step there are precedence constraints added to the success pathways to dictate the flow, the dependant variable isUpdateSchedule. This will allow the variability to either call an update schedule stored procedure or a create schedule stored procedure
Schedule Exists
There exists a current schedule by this name in the database.
public void Main() { String strJobScheduleSQL; strJobScheduleSQL = "exec msdb.dbo.sp_update_jobschedule @job_name ='" + Dts.Variables["JobName"].Value + "', @name='" + Dts.Variables["ScheduleName"].Value + "', @freq_type = 1, @active_start_date = '" + Dts.Variables["ScheduleDate"].Value + "'"; Dts.Variables["sqlSchedule"].Value = strJobScheduleSQL;
Dts.TaskResult = (int)ScriptResults.Success; }
public void Main() { String strJobScheduleSQL; strJobScheduleSQL = "EXEC msdb.dbo.sp_add_schedule @schedule_name = '" + Dts.Variables["ScheduleName"].Value + "', @freq_type = 1, @active_start_date = '" + Dts.Variables["ScheduleDate"].Value + "' EXEC msdb.dbo.sp_attach_schedule @job_name = '" + Dts.Variables["JobName"].Value + "', @schedule_name = '" + Dts.Variables["ScheduleName"].Value + "'"; Dts.Variables["sqlSchedule"].Value = strJobScheduleSQL; Dts.TaskResult = (int)ScriptResults.Success; }
Last Task
To make all of this functional, you will need to deploy this script to your SQL server. There are several ways to do this, which I wont discuss here. After the package is deployed to your server, create a job that references the package, and then run the job. If the schedule is non-existent a job schedule will be created, or if it does exist it will be updated.
Limits
These are limitations of this process. 1. The user needs to add mail messages for failure of either update or insert of schedule. 2. This is not covered, but the administrator could add some more input parameters that could set the run for a specific time if required. Other Considerations 1. By making the package even more generic and passing the needed values into the package when the job runs, this process could become even more versatile.
2. By changing the MessageSourceType to a variable, and then passing the message in and using each scripting step along the way to adjust the message to what is happening in that step, would allow me to remove all but two mail steps; success and failure. 3. Merging the Create and Update parts of step 7 would consolidate a functional duplicate.
Summary
What has been shown is a methodology for jobs that can self-schedule, based on a calculable date, and in this case handles a periodic data load. Once one understands the basic flow, its really a pretty simple idea as demonstrated by the following list:
Do Load Set variable for job name, schedule name, and SQL to generate next run date Execute the previous step's sql and place value in variable Set variable for Job Schedule Lookup Execute the previous step's sql and place value in variable A) if Schedule exists create update SQL and place in variable B) if Schedule does not exist create Schedule create SQL and place in variable Depending on if the Schedule exists execute the proper SQL statement Send mail message of results So far, this methodology has worked well and hasnt failed yet. With the minor addition of mail messages to #7, I should always get a message telling me the results of the run. So there you have it, a self-scheduling job that handles a data load. Th