SQL Agen Scheduler - Updated
This commit is contained in:
@ -0,0 +1,223 @@
|
||||
USE [msdb];
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE dbo.usp_CreateWeeklySchedules
|
||||
@Env VARCHAR(10) = 'DEVL' -- Added parameter with default value
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
|
||||
DECLARE
|
||||
@JobName SYSNAME,
|
||||
@FrequencyPattern NVARCHAR(MAX),
|
||||
@StartTime VARCHAR(50),
|
||||
@ScheduleName SYSNAME,
|
||||
@StartTimeInt INT,
|
||||
@FreqInterval INT,
|
||||
@ActiveDate INT,
|
||||
@computedFreq INT,
|
||||
@dbName SYSNAME; -- Added variable for database name
|
||||
|
||||
-- Determine database name based on environment
|
||||
SET @dbName = CASE @Env
|
||||
WHEN 'DEVL' THEN 'DevlDUTASJobSchedule'
|
||||
WHEN 'TEST' THEN 'TestDUTASJobSchedule'
|
||||
WHEN 'PROD' THEN 'ProdDUTASJobSchedule'
|
||||
END;
|
||||
|
||||
SET @ActiveDate = CONVERT(INT, CONVERT(CHAR(8), GETDATE(), 112));
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Dynamic SQL for cursor to fetch active weekly jobs from appropriate database
|
||||
--------------------------------------------------------------------------
|
||||
DECLARE @Sql NVARCHAR(MAX);
|
||||
SET @Sql = N'
|
||||
DECLARE job_cursor CURSOR FAST_FORWARD FOR
|
||||
SELECT
|
||||
JobName,
|
||||
FrequencyPattern,
|
||||
ScheduledStartTime
|
||||
FROM ' + QUOTENAME(@dbName) + N'.dbo.JobControl
|
||||
WHERE UPPER(Frequency) = ''WEEKLY''
|
||||
AND IsActive = 1;';
|
||||
|
||||
-- Execute dynamic SQL to declare cursor
|
||||
EXEC sp_executesql @Sql;
|
||||
|
||||
OPEN job_cursor;
|
||||
FETCH NEXT FROM job_cursor INTO @JobName, @FrequencyPattern, @StartTime;
|
||||
|
||||
WHILE @@FETCH_STATUS = 0
|
||||
BEGIN
|
||||
BEGIN TRY
|
||||
------------------------------------------------------------------
|
||||
-- Reset per-job variables
|
||||
------------------------------------------------------------------
|
||||
SET @FreqInterval = 0;
|
||||
SET @computedFreq = 0;
|
||||
SET @StartTimeInt = NULL;
|
||||
SET @ScheduleName = NULL;
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Correctly format the start time (HHMMSS without extra zeros)
|
||||
------------------------------------------------------------------
|
||||
SET @StartTime = LTRIM(RTRIM(ISNULL(@StartTime, '00:00:00')));
|
||||
|
||||
-- Parse time and convert to HHMMSS integer
|
||||
DECLARE @TimeParts TABLE (part NVARCHAR(10), idx INT);
|
||||
INSERT INTO @TimeParts (part, idx)
|
||||
SELECT value, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1
|
||||
FROM STRING_SPLIT(LEFT(@StartTime, 8), ':');
|
||||
|
||||
DECLARE @Hours INT, @Minutes INT, @Seconds INT;
|
||||
|
||||
SELECT @Hours = CAST(part AS INT) FROM @TimeParts WHERE idx = 0;
|
||||
SELECT @Minutes = CAST(part AS INT) FROM @TimeParts WHERE idx = 1;
|
||||
SELECT @Seconds = CAST(part AS INT) FROM @TimeParts WHERE idx = 2;
|
||||
|
||||
-- Ensure valid time ranges
|
||||
SET @Hours = ISNULL(@Hours, 0);
|
||||
SET @Minutes = ISNULL(@Minutes, 0);
|
||||
SET @Seconds = ISNULL(@Seconds, 0);
|
||||
|
||||
IF @Hours < 0 OR @Hours > 23 SET @Hours = 0;
|
||||
IF @Minutes < 0 OR @Minutes > 59 SET @Minutes = 0;
|
||||
IF @Seconds < 0 OR @Seconds > 59 SET @Seconds = 0;
|
||||
|
||||
SET @StartTimeInt = (@Hours * 10000) + (@Minutes * 100) + @Seconds;
|
||||
|
||||
SET @ScheduleName = CONCAT(@JobName, '_WeeklySchedule');
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Parse JSON days using a local temporary table
|
||||
------------------------------------------------------------------
|
||||
CREATE TABLE #Days (DayName NVARCHAR(10));
|
||||
|
||||
INSERT INTO #Days (DayName)
|
||||
SELECT TRIM(value)
|
||||
FROM OPENJSON(ISNULL(@FrequencyPattern, '{}'), '$.Days');
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Compute bitmask correctly (values should be 1-127)
|
||||
------------------------------------------------------------------
|
||||
SELECT @computedFreq = ISNULL(SUM(
|
||||
CASE UPPER(DayName)
|
||||
WHEN 'SUN' THEN 1
|
||||
WHEN 'MON' THEN 2
|
||||
WHEN 'TUE' THEN 4
|
||||
WHEN 'WED' THEN 8
|
||||
WHEN 'THU' THEN 16
|
||||
WHEN 'FRI' THEN 32
|
||||
WHEN 'SAT' THEN 64
|
||||
ELSE 0
|
||||
END
|
||||
), 0)
|
||||
FROM #Days;
|
||||
|
||||
DROP TABLE #Days; -- Explicitly drop the temp table
|
||||
|
||||
SET @FreqInterval = ISNULL(@computedFreq, 0);
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Validate freq_interval (must be 1..127)
|
||||
------------------------------------------------------------------
|
||||
IF @FreqInterval < 1 OR @FreqInterval > 127
|
||||
BEGIN
|
||||
PRINT 'Warning: Weekly job ' + @JobName +
|
||||
' has invalid freq_interval (' + ISNULL(CAST(@FreqInterval AS VARCHAR(10)), 'NULL') +
|
||||
'). Days found: ' + ISNULL(@FrequencyPattern, 'None') + '. Skipping.';
|
||||
FETCH NEXT FROM job_cursor INTO @JobName, @FrequencyPattern, @StartTime;
|
||||
CONTINUE;
|
||||
END
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Debug output to verify calculations
|
||||
------------------------------------------------------------------
|
||||
PRINT 'Job: ' + @JobName +
|
||||
', Days: ' + @FrequencyPattern +
|
||||
', FreqInterval: ' + CAST(@FreqInterval AS VARCHAR(3)) +
|
||||
', StartTime: ' + CAST(@StartTimeInt AS VARCHAR(6));
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Safely detach and delete any existing schedule with this name
|
||||
-- Use TRY/CATCH for schedule operations since non-existence is expected
|
||||
------------------------------------------------------------------
|
||||
BEGIN TRY
|
||||
DECLARE @schedule_id INT;
|
||||
DECLARE @attach_count INT;
|
||||
|
||||
-- Check if schedule exists and get its ID
|
||||
SELECT @schedule_id = s.schedule_id
|
||||
FROM msdb.dbo.sysschedules s
|
||||
JOIN msdb.dbo.sysjobschedules js ON s.schedule_id = js.schedule_id
|
||||
JOIN msdb.dbo.sysjobs j ON j.job_id = js.job_id
|
||||
WHERE j.name = @JobName AND s.name = @ScheduleName;
|
||||
|
||||
IF @schedule_id IS NOT NULL
|
||||
BEGIN
|
||||
-- Detach from this job (if attached)
|
||||
EXEC msdb.dbo.sp_detach_schedule
|
||||
@job_name = @JobName,
|
||||
@schedule_name = @ScheduleName;
|
||||
|
||||
-- Check if schedule still attached to other jobs
|
||||
SELECT @attach_count = COUNT(*)
|
||||
FROM msdb.dbo.sysjobschedules js
|
||||
WHERE js.schedule_id = @schedule_id;
|
||||
|
||||
IF @attach_count = 0
|
||||
BEGIN
|
||||
EXEC msdb.dbo.sp_delete_schedule
|
||||
@schedule_name = @ScheduleName;
|
||||
PRINT 'Existing schedule deleted: ' + @ScheduleName;
|
||||
END
|
||||
ELSE
|
||||
BEGIN
|
||||
PRINT 'Notice: schedule ' + @ScheduleName + ' could not be deleted because it is still attached to other jobs.';
|
||||
END
|
||||
END
|
||||
END TRY
|
||||
BEGIN CATCH
|
||||
-- Schedule operations might fail if schedule doesn't exist, which is fine
|
||||
PRINT 'Notice: ' + ERROR_MESSAGE() + ' - proceeding with new schedule creation.';
|
||||
END CATCH
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Create the unified weekly schedule with subday config
|
||||
------------------------------------------------------------------
|
||||
EXEC msdb.dbo.sp_add_schedule
|
||||
@schedule_name = @ScheduleName,
|
||||
@enabled = 1,
|
||||
@freq_type = 8, -- Weekly
|
||||
@freq_interval = @FreqInterval, -- Bitmask of weekdays
|
||||
@freq_recurrence_factor = 1, -- Every week
|
||||
@freq_subday_type = 1, -- Once per day
|
||||
@freq_subday_interval = 1,
|
||||
@active_start_time = @StartTimeInt,
|
||||
@active_start_date = @ActiveDate;
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Attach the schedule to the job
|
||||
------------------------------------------------------------------
|
||||
EXEC msdb.dbo.sp_attach_schedule
|
||||
@job_name = @JobName,
|
||||
@schedule_name = @ScheduleName;
|
||||
|
||||
PRINT 'Weekly schedule created for job: ' + @JobName +
|
||||
' (Days=' + CAST(@FreqInterval AS VARCHAR(10)) +
|
||||
', Time=' + RIGHT('000000' + CAST(@StartTimeInt AS VARCHAR(6)), 6) + ')';
|
||||
|
||||
END TRY
|
||||
BEGIN CATCH
|
||||
PRINT 'Error scheduling job ' + ISNULL(@JobName, 'Unknown') + ': ' + ERROR_MESSAGE();
|
||||
END CATCH;
|
||||
|
||||
FETCH NEXT FROM job_cursor INTO @JobName, @FrequencyPattern, @StartTime;
|
||||
END
|
||||
|
||||
CLOSE job_cursor;
|
||||
DEALLOCATE job_cursor;
|
||||
|
||||
PRINT 'All weekly job schedules processed for ' + @dbName;
|
||||
END;
|
||||
GO
|
||||
Reference in New Issue
Block a user