Во-первых, вы должны ссылаться на sysschedules . Но, насколько я понимаю, это опечатка. Это
active_start_time Время в любой день между active_start_date и active_end_date этой работы
начинает выполнять. Время отформатировано в формате ЧЧММСС с использованием 24-часовых часов.
следует читать как
active_start_time Время в любой день между active_start_time и active_end_time этой работой
начинает выполнять. Время отформатировано в формате ЧЧММСС с использованием 24-часовых часов.
И учтите это:
active_start_date Дата, когда может начаться выполнение задания. Дата отформатирована как
YYYYMMDD. NULL указывает сегодняшнюю дату.
Это означает, что если вы настраиваете повторяющееся задание на запуск каждый день каждый час и устанавливаете active_start_time = 100000 и active_start_date = 20120323, то задание не будет работать до 23 марта 2012 г. 10:00.
Но если вы создаете однократную задачу, то в этих полях указываются точная дата и время начала.
Что касается поиска подходящих событий, мое мнение следующее. Когда вы обновляете что-то существенное (например, тип расписания или время запуска) или когда повторяющееся расписание вызывает выполнение следующего задания, SQL Agent рассчитывает время следующего запуска для расписания и сохраняет его в sysjobschedules.next_run_date
.
Итак, у него всегда есть список последующих выполнений, и он не решает проблему «найти подходящие события для определенной даты». И я думаю, что вы должны реализовать свою систему таким же образом.
Но если вы настаиваете на том, чтобы делать это таким образом, мы можем подумать о запросе T-SQL для этого.
UPDATE
Ниже приведен скрипт, который может помочь вам в вашей задаче. На данный момент он работает для двух типов расписания:
1. начать один раз
2. начинать ежедневно каждые N дней, один раз в день
Насколько я понимаю из вашего комментария вы будете их использовать. Вы можете добавить дополнительные типы, как только они вам понадобятся, таким же образом (UNION ALL ... UNION ALL ...
).
Функция msdb_time_convert
преобразует целое число ЧЧММСС в тип данных TIME.
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
Вы можете указать любую дату / время в переменной @find_date
, чтобы найти следующие запуски в разные моменты времени.
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