Generate SQL Job Schedule Description

I was actually calling the system stored procedure "msdb.dbo.sp_help_jobschedule" in my previous post about modifying column list from a called stored procedure,

While working on that I noticed that [more]the description (schedule_description) being returned by stored procedure (if you set @include_description = 1) returns date and times as integer values (rather than date/time format).

While looking around I found this feedback from microsoft connect : sp_get_schedule_description produces basic output, be nice if it had formatted dates & times (you might be required to login to view it)

Turns out the behavior was changed from SQL2000 to SQL2005 and won't be changed(or corrected should I say) since other applications that depended on the format might break.

So I figured I'd have a function/method for returning a more user friendly description instead.

Found this article as a baseline: Generate Job Schedule Description and created the functions below (GetScheduleDescription and GetTimeString)

— START

IF EXISTS (
  SELECT *
  FROM sys.objects
  WHERE
    object_id = OBJECT_ID(N'[dbo].[GetTimeString]')
    AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[GetTimeString]

GO

— =============================================
— Author: Ryan Garaygay
— Create date: 03/25/2008
— Description:    Return Time String Representation from INT (scheduled job format, HHmmss)
— =============================================
CREATE FUNCTION [dbo].[GetTimeString](@timeInteger INT)
RETURNS NVARCHAR(255)
AS
BEGIN

— convert to 12hr time
DECLARE @originalTimeInteger INT
SET @originalTimeInteger = @timeInteger
IF(@timeInteger >= 130000)
  SET @timeInteger = @timeInteger – 120000

— convert to 6 chars (pad if necessary)
DECLARE @TM VARCHAR(255)
SET @TM = REPLACE(STR(@timeInteger, 6), SPACE(1), '0')

DECLARE @RETVAL VARCHAR(255)
SET @RETVAL =
  SUBSTRING(@TM,1,2) + ':' +
  SUBSTRING(@TM,3,2) + ':' +
  SUBSTRING(@TM,5,2)
  + CASE
    WHEN @originalTimeInteger < 120000 THEN ' AM'
    ELSE ' PM'
  END
  RETURN @RETVAL
END
GO

IF EXISTS (
  SELECT *
  FROM sys.objects
  WHERE
    object_id = OBJECT_ID(N'[dbo].[GetScheduleDescription]')
    AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[GetScheduleDescription]

GO

— =============================================
— Author: Ryan Garaygay
— Create date: 03/25/2008
— Description:    Return Schedule Description
— a modification of sp_get_schedule_description
— but there is an issue with SQL2005 where the date/times returned are in INT
— instead of recognizable date/time formats
— =============================================
CREATE FUNCTION [dbo].[GetScheduleDescription](
  @freq_type              INT          = NULL,
  @freq_interval          INT          = NULL,
  @freq_subday_type       INT          = NULL,
  @freq_subday_interval   INT          = NULL,
  @freq_relative_interval INT          = NULL,
  @freq_recurrence_factor INT          = NULL,
  @active_start_date      INT          = NULL,
  @active_end_date        INT          = NULL,
  @active_start_time      INT          = NULL,
  @active_end_time        INT          = NULL,
  @enabled                BIT          = NULL)
RETURNS NVARCHAR(255)
AS
BEGIN
  DECLARE @schedule_description NVARCHAR(255)
  SET @schedule_description =
  'Occurs ' +
  CASE
    WHEN @freq_type = 0x1 — OneTime
      THEN
        'once on '
        + CONVERT(
            CHAR(10)
            , CAST( CAST( @active_start_date AS VARCHAR ) AS DATETIME )
            , 101 — mm/dd/yyyy
          )
    WHEN @freq_type = 0x4 — Daily
      THEN
        CASE
          WHEN @freq_interval = 1
            THEN 'daily '
          WHEN @freq_interval > 1
            THEN 'every '
            + CAST( @freq_interval AS VARCHAR )
            + ' days '
        END
    WHEN @freq_type = 0x8 — weekly
      THEN
        CASE
          WHEN @freq_recurrence_factor = 1
            THEN 'weekly on '
          WHEN @freq_recurrence_factor > 1
            THEN 'every '
            + CAST( @freq_recurrence_factor AS VARCHAR )
            + ' weeks on '
        END
        + LEFT(
             CASE WHEN @freq_interval &  1 =  1 THEN 'Sunday, '    ELSE '' END
           + CASE WHEN @freq_interval &  2 =  2 THEN 'Monday, '    ELSE '' END
           + CASE WHEN @freq_interval &  4 =  4 THEN 'Tuesday, '   ELSE '' END
           + CASE WHEN @freq_interval &  8 =  8 THEN 'Wednesday, ' ELSE '' END
           + CASE WHEN @freq_interval & 16 = 16 THEN 'Thursday, '  ELSE '' END
           + CASE WHEN @freq_interval & 32 = 32 THEN 'Friday, '    ELSE '' END
           + CASE WHEN @freq_interval & 64 = 64 THEN 'Saturday, '  ELSE '' END
         , LEN(
                    CASE WHEN @freq_interval &  1 =  1 THEN 'Sunday, '    ELSE '' END
                  + CASE WHEN @freq_interval &  2 =  2 THEN 'Monday, '    ELSE '' END
                  + CASE WHEN @freq_interval &  4 =  4 THEN 'Tuesday, '   ELSE '' END
                  + CASE WHEN @freq_interval &  8 =  8 THEN 'Wednesday, ' ELSE '' END
                  + CASE WHEN @freq_interval & 16 = 16 THEN 'Thursday, '  ELSE '' END
                  + CASE WHEN @freq_interval & 32 = 32 THEN 'Friday, '    ELSE '' END
                  + CASE WHEN @freq_interval & 64 = 64 THEN 'Saturday, '  ELSE '' END
              ) – 1  — LEN() ignores trailing spaces
        )
     WHEN @freq_type = 0x10 — monthly
         THEN
             CASE
                 WHEN @freq_recurrence_factor = 1
                     THEN 'monthly on the '
                 WHEN @freq_recurrence_factor > 1
                     THEN 'every '
                        + CAST( @freq_recurrence_factor AS VARCHAR )
                        + ' months on the '
             END
           + CAST( @freq_interval AS VARCHAR )
           + CASE
                 WHEN @freq_interval IN ( 1, 21, 31 ) THEN 'st'
                 WHEN @freq_interval IN ( 2, 22     ) THEN 'nd'
                 WHEN @freq_interval IN ( 3, 23     ) THEN 'rd'
                 ELSE 'th'
             END
     WHEN @freq_type = 0x20 — monthly relative
         THEN
             CASE
                 WHEN @freq_recurrence_factor = 1
                     THEN 'monthly on the '
                 WHEN @freq_recurrence_factor > 1
                     THEN 'every '
                        + CAST( @freq_recurrence_factor AS VARCHAR )
                        + ' months on the '
             END
           + CASE @freq_relative_interval
                 WHEN 0x01 THEN 'first '
                 WHEN 0x02 THEN 'second '
                 WHEN 0x04 THEN 'third '
                 WHEN 0x08 THEN 'fourth '
                 WHEN 0x10 THEN 'last '
             END
           + CASE @freq_interval
                 WHEN  1 THEN 'Sunday'
                 WHEN  2 THEN 'Monday'
                 WHEN  3 THEN 'Tuesday'
                 WHEN  4 THEN 'Wednesday'
                 WHEN  5 THEN 'Thursday'
                 WHEN  6 THEN 'Friday'
                 WHEN  7 THEN 'Saturday'
                 WHEN  8 THEN 'day'
                 WHEN  9 THEN 'week day'
                 WHEN 10 THEN 'weekend day'
             END
     WHEN @freq_type = 0x40
         THEN 'Automatically starts when SQLServerAgent start@'
     WHEN @freq_type = 0x80
         THEN 'Starts whenever the CPUs become idle'
     ELSE ''
   END
 + CASE
     WHEN @freq_subday_type = 0x1 OR @freq_type = 0x1
         THEN ' at '
           + dbo.[GetTimeString](@active_start_time)
     WHEN @freq_subday_type IN ( 0x2, 0x4, 0x8 )
         THEN ' running every '
           + CAST( @freq_subday_interval AS VARCHAR )
           + CASE @freq_subday_type
                 WHEN 0x2 THEN ' second'
                 WHEN 0x4 THEN ' minute'
                 WHEN 0x8 THEN ' hour'
             END
           + CASE
                 WHEN @freq_subday_interval > 1 THEN 's'
                 ELSE ''
             END
            + ' between '
            + dbo.[GetTimeString](@active_start_time)
            + ' and '
            + dbo.[GetTimeString](@active_end_time)
     ELSE ''
   END
 + CASE
     WHEN @freq_type IN ( 4, 8, 16, 32 ) — daily, weekly, monthly and monthly relative
         THEN '. Schedule will be used '
          +
            CASE
              WHEN (@active_end_date IS NULL OR @active_end_date = 99991231)
                THEN ' starting '
                  + CONVERT(
                    CHAR(10)
                    , CAST( CAST( @active_start_date AS VARCHAR ) AS DATETIME )
                    , 101 — mm/dd/yyyy
                  )
                  + '.'
              ELSE
                ' between '
                  + CONVERT(
                    CHAR(10)
                    , CAST( CAST( @active_start_date AS VARCHAR ) AS DATETIME )
                    , 101 — mm/dd/yyyy
                  )
                  + ' and '
                  + CONVERT(
                    CHAR(10)
                    , CAST( CAST( @active_end_date AS VARCHAR ) AS DATETIME )
                    , 101 — mm/dd/yyyy
                  )
                  + '.'
            END
     ELSE ''
   END

  RETURN @schedule_description
END

GO

IF EXISTS (
  SELECT *
  FROM sys.objects
  WHERE
    object_id = OBJECT_ID(N'[dbo].[CM1_SEL_ScheduleByJobID]')
    AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[CM1_SEL_ScheduleByJobID]

— END

Again, as previously mentioned, used INSERT-EXEC to simply store the values of my "msdb.dbo.sp_help_jobschedule" query to a table variable. Then for the final SELECT statement, I called my new GetScheduleDescription

      [ScheduleDescription] = dbo.GetScheduleDescription(
          freq_type,
          freq_interval,
          freq_subday_type,
          freq_subday_interval,
          freq_relative_interval,
          freq_recurrence_factor,
          active_start_date,
          active_end_date,
          active_start_time,
          active_end_time,
          enabled)

Hope this helps anyone. 

REVISED as of 3/27/08 – handling of 12:mm PM and changes to further enhance the description returned.


Posted

in

by

Tags:

Comments

2 responses to “Generate SQL Job Schedule Description”

  1. Siji Avatar
    Siji

    Could you help with a script to create a list of jobs and its schedule descriptions without creating a function?

    1. Ryan Garaygay Avatar
      Ryan Garaygay

      hi Siji, it looks like it is possible – just move the logic out of the function but the downside would be readability. you might be able to do it using case statements within the select code