Using sysschedules as a table for SQL Server events

I am trying to create a repeating calendar of events. It looks like the sysschedules table in the msdb database could do the job as accurately as possible.

However, I ran into a few problems, hoping someone could help.

a) active_start_date : is the date the event first occurs? Or any start date or before the event?

b) how can I find relevant events (once, daily, weekly, monthly, etc.) on a specific date?

Edit: I do not use the sysschedules table sysschedules . Rather, a new table with the same columns is created.

+4
source share
1 answer

You must refer to sysschedules first . But as I understand it, there is a typo. it

active_start_time The time on any day between active_start_date and active_end_date that the job starts execution. Time is formatted by HHMMSS using 24-hour mode.

should read like

active_start_time The time any day between active_start_time and active_end_time that the job starts execution. Time is formatted by HHMMSS using 24-hour mode.

And consider this:

active_start_date The start date of the job. The date is formatted as YYYYMMDD. NULL indicates the date today.

This means that if you set up a recurring task to run every day every hour and set active_start_time = 100000 and active_start_date = 20120323, then the work will not work until March 23, 2012 10 AM.
But if you are creating a one-time task, then these fields contain the exact start date and time.

Regarding the search for suitable events, my opinion is as follows. When you update something significant (such as a schedule type or start time) or when a repeating schedule increases the next job, the SQL agent calculates the next run time for the schedule and stores it in sysjobschedules.next_run_date .

Thus, he always has a list of queues the next time and does not solve the problem of โ€œfinding the appropriate events for a specific dateโ€. And I think you should implement your system in the same way.

But if you insist on doing it this way, we might think of a T-SQL query for this.

UPDATE
Below is a script that can help you complete your task. Currently it works for two types of schedules:
1. start once
2. start daily every N days, once a day
As far as I understand from your comment, you will use them. You can add additional types as soon as you need them in the same way ( UNION ALL ... UNION ALL ... ).

The msdb_time_convert function converts an integer HHMMSS to a TIME data type.

 CREATE FUNCTION msdb_time_convert ( @int_time INT ) RETURNS TIME(0) AS BEGIN IF NOT (@int_time BETWEEN 0 AND 235959) RETURN NULL DECLARE @str VARCHAR(32) = CAST(@int_time AS VARCHAR(32)) SELECT @str = REPLICATE('0', 6 - LEN(@str)) + @str SELECT @str = STUFF(@str, 3, 0, ':') SELECT @str = STUFF(@str, 6, 0, ':') RETURN CONVERT(TIME(0), @str, 108) END GO 

You can specify any datetime in the @find_date variable to find the following runs at different points in time.

 DECLARE @find_date DATETIME = GETDATE() ;WITH CTE AS ( SELECT CONVERT(DATE, CAST(active_start_date AS VARCHAR(32)), 112) AS active_start_date, CONVERT(DATE, CAST(active_end_date AS VARCHAR(32)), 112) AS active_end_date, dbo.msdb_time_convert(active_start_time) AS active_start_time, dbo.msdb_time_convert(active_end_time) AS active_end_time, schedule_id, schedule_uid, name, enabled, freq_type, freq_interval, freq_subday_type, freq_subday_interval, freq_relative_interval, freq_recurrence_factor, CAST(@find_date AS DATE) AS today_date, CAST(@find_date AS TIME(0)) AS today_time, DATEADD(day, DATEDIFF(day, CONVERT(DATETIME, CAST(active_start_date AS VARCHAR(32)), 112) - 1, @find_date) % NULLIF(freq_interval, 0), CAST(@find_date AS DATE)) AS next_daily_day FROM dbo.sysschedules ) SELECT schedule_id, name, CAST(active_start_date AS DATETIME) + active_start_time AS next_run_datetime FROM CTE WHERE enabled = 1 AND freq_type = 1 -- 1 = One time only AND CAST(active_start_date AS DATETIME) + active_start_time >= @find_date UNION ALL SELECT schedule_id, name, DATEADD( DAY, CASE WHEN CAST(next_daily_day AS DATETIME) + active_start_time > @find_date THEN 0 ELSE freq_interval END, CAST(next_daily_day AS DATETIME) + active_start_time ) AS next_run_datetime FROM CTE WHERE enabled = 1 AND freq_type = 4 -- 4 = Daily (Every freq_interval days) AND freq_subday_type = 1 -- 1 = At the specified time AND CAST(active_end_date AS DATETIME) + active_end_time >= @find_date 
+4
source

Source: https://habr.com/ru/post/1402764/


All Articles