930 lines
30 KiB
Transact-SQL
930 lines
30 KiB
Transact-SQL
/*=============================================================================
|
|
|
|
Création d'un package pour la gestion du monitoring des status des Jobs SQL
|
|
|
|
-> Création des tables
|
|
-> Création des FK et index
|
|
-> Deploy de la SP d'initialisation du status des jobs : mon.Initialize_Jobs_Status
|
|
-> Deploy de la SP de mise à jour du status des jobs : mon.Maj_Jobs_Status
|
|
-> Deploy de la fonction du calcul de prochain schedule : GetNextScheduleForJob
|
|
|
|
Création : 13.07.2023 / FLA
|
|
|
|
Modifications :
|
|
17.08.2023 / FLA : Changement de methode d'update, changement du calcul du prochain schedule, add SP to check status
|
|
21.09.2023 / FLA : Improve performance for function GetNextScheduleForJob and for SP Maj_Jobs_Status
|
|
|
|
|
|
=============================================================================*/
|
|
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
/* STRUCTURE */
|
|
/* */
|
|
/***********************************************************************/
|
|
USE HCITools;
|
|
|
|
IF NOT EXISTS ( SELECT *
|
|
FROM sys.objects
|
|
WHERE object_id = OBJECT_ID(N'[mon].[Job_monitoring_config]')
|
|
AND type IN ( N'U' ))
|
|
BEGIN
|
|
|
|
CREATE TABLE [mon].[Job_monitoring_config](
|
|
[Job_monitoring_config_ID] [INT] IDENTITY(1,1) NOT NULL,
|
|
[JMC_name] [VARCHAR](255) NOT NULL,
|
|
[JMC_need_history] [BIT] NOT NULL,
|
|
[JMC_caller] [VARCHAR](255) NULL,
|
|
[JMC_ignore] [BIT] NOT NULL,
|
|
CONSTRAINT [PK_Job_monitoring_config] PRIMARY KEY CLUSTERED
|
|
(
|
|
[Job_monitoring_config_ID] ASC
|
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
|
) ON [PRIMARY]
|
|
END
|
|
|
|
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mon].[DF_JMC_need_history]') AND type = 'D')
|
|
BEGIN
|
|
ALTER TABLE [mon].[Job_monitoring_config] ADD CONSTRAINT DF_JMC_need_history DEFAULT (1) FOR [JMC_need_history]
|
|
END
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mon].[DF_JMC_ignore]') AND type = 'D')
|
|
BEGIN
|
|
ALTER TABLE [mon].[Job_monitoring_config] ADD CONSTRAINT DF_JMC_ignore DEFAULT (0) FOR [JMC_ignore]
|
|
END
|
|
GO
|
|
|
|
|
|
IF NOT EXISTS (SELECT * FROM ::fn_listextendedproperty ('MS_Description', 'Schema', 'mon', 'Table', 'Job_monitoring_config', 'Column', 'JMC_need_history'))
|
|
BEGIN
|
|
EXEC sp_addextendedproperty 'MS_Description', '0: same row updated in table Job_monitoring_history, 1:one row for each execution of job', 'Schema', [mon], 'table', [Job_monitoring_config], 'column', [JMC_need_history]
|
|
END
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT * FROM ::fn_listextendedproperty ('MS_Description', 'Schema', 'mon', 'Table', 'Job_monitoring_config', 'Column', 'JMC_caller'))
|
|
BEGIN
|
|
EXEC sp_addextendedproperty 'MS_Description', 'Name of job If job called by another one', 'Schema', [mon], 'table', [Job_monitoring_config], 'column', [JMC_caller]
|
|
END
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT * FROM ::fn_listextendedproperty ('MS_Description', 'Schema', 'mon', 'Table', 'Job_monitoring_config', 'Column', 'JMC_ignore'))
|
|
BEGIN
|
|
EXEC sp_addextendedproperty 'MS_Description', '0: To monitor, 1:To don''t monitor', 'Schema', [mon], 'table', [Job_monitoring_config], 'column', [JMC_ignore]
|
|
END
|
|
GO
|
|
|
|
IF NOT EXISTS ( SELECT 1
|
|
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
|
|
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY'
|
|
AND TABLE_NAME = N'Job_monitoring_config')
|
|
BEGIN
|
|
ALTER TABLE [mon].[Job_monitoring_config]
|
|
ADD CONSTRAINT [PK_Job_monitoring_config]
|
|
PRIMARY KEY CLUSTERED ([Job_monitoring_config_ID] ASC);
|
|
END;
|
|
|
|
|
|
IF NOT EXISTS ( SELECT 1
|
|
FROM sys.indexes
|
|
WHERE object_id = OBJECT_ID(N'[mon].[Job_monitoring_config]')
|
|
AND name = N'NCIX_Job_monitoring_config_COL_JMC_name')
|
|
BEGIN
|
|
CREATE NONCLUSTERED INDEX [NCIX_Job_monitoring_config_COL_JMC_name]
|
|
ON [mon].[Job_monitoring_config] ([JMC_name] ASC)
|
|
INCLUDE (JMC_need_history, JMC_caller, JMC_ignore);
|
|
END;
|
|
|
|
IF NOT EXISTS ( SELECT *
|
|
FROM sys.objects
|
|
WHERE object_id = OBJECT_ID(N'[mon].[Job_monitoring_history]')
|
|
AND type IN ( N'U' ))
|
|
BEGIN
|
|
CREATE TABLE [mon].[Job_monitoring_history](
|
|
[Job_monitoring_history_ID] [INT] IDENTITY(1,1) NOT NULL,
|
|
[JMH_job_monitoring_config_ID] [INT] NOT NULL,
|
|
[JMH_next_schedule] [DATETIME] NULL,
|
|
[JMH_monitoring_status] [TINYINT] NOT NULL,
|
|
[JMH_job_status] [TINYINT] NULL,
|
|
[JMH_error_message] [NVARCHAR](4000) NULL,
|
|
[JMH_update_status] [DATETIME] NOT NULL,
|
|
[JMH_monitoring_date] [DATETIME] NULL,
|
|
CONSTRAINT [PK_Job_monitoring_history] PRIMARY KEY CLUSTERED
|
|
(
|
|
[Job_monitoring_history_ID] ASC
|
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
|
) ON [PRIMARY]
|
|
END
|
|
|
|
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mon].[DF_JMH_monitoring_status]') AND type = 'D')
|
|
BEGIN
|
|
ALTER TABLE [mon].[Job_monitoring_history] ADD CONSTRAINT DF_JMH_monitoring_status DEFAULT ((0)) FOR [JMH_monitoring_status]
|
|
END
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mon].[DF_JMH_update_status]') AND type = 'D')
|
|
BEGIN
|
|
ALTER TABLE [mon].[Job_monitoring_history] ADD CONSTRAINT DF_JMH_update_status DEFAULT (GETDATE()) FOR [JMH_update_status]
|
|
END
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT * FROM ::fn_listextendedproperty ('MS_Description', 'Schema', 'mon', 'Table', 'Job_monitoring_history', 'Column', 'JMH_monitoring_status'))
|
|
BEGIN
|
|
EXEC sp_addextendedproperty 'MS_Description', '0: No error, 1:Error not checked, 2:Error checked', 'Schema', [mon], 'table', [Job_monitoring_history], 'column', [JMH_monitoring_status]
|
|
END
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT * FROM ::fn_listextendedproperty ('MS_Description', 'Schema', 'mon', 'Table', 'Job_monitoring_history', 'Column', 'JMH_job_status'))
|
|
BEGIN
|
|
EXEC sp_addextendedproperty 'MS_Description', '0 = Failed
|
|
1 = Succeeded
|
|
2 = No execution', 'Schema', [mon], 'table', [Job_monitoring_history], 'column', [JMH_job_status]
|
|
END
|
|
GO
|
|
|
|
|
|
IF NOT EXISTS ( SELECT 1
|
|
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
|
|
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY'
|
|
AND TABLE_NAME = N'Job_monitoring_history')
|
|
BEGIN
|
|
ALTER TABLE [mon].[Job_monitoring_history]
|
|
ADD CONSTRAINT [PK_Job_monitoring_history]
|
|
PRIMARY KEY CLUSTERED ([Job_monitoring_history_ID] ASC);
|
|
END;
|
|
|
|
IF NOT EXISTS ( SELECT 1
|
|
FROM sys.foreign_keys
|
|
WHERE object_id = OBJECT_ID(N'mon.FK_Job_monitoring_config_COL_Job_monitoring_config_ID')
|
|
AND parent_object_id = OBJECT_ID(N'[mon].[Job_monitoring_history]'))
|
|
BEGIN
|
|
ALTER TABLE [mon].[Job_monitoring_history]
|
|
ADD CONSTRAINT [FK_Job_monitoring_config_COL_Job_monitoring_config_ID]
|
|
FOREIGN KEY ([JMH_Job_monitoring_config_ID])
|
|
REFERENCES [mon].[Job_monitoring_config] ([Job_monitoring_config_ID]) ON DELETE NO ACTION ON UPDATE NO ACTION;
|
|
END;
|
|
GO
|
|
|
|
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mon].[Initialize_Jobs_Status]') AND type IN (N'P', N'PC'))
|
|
DROP PROCEDURE [mon].[Initialize_Jobs_Status]
|
|
GO
|
|
|
|
CREATE PROCEDURE [mon].[Initialize_Jobs_Status]
|
|
@in_debug TINYINT = 0,
|
|
@in_JobName NVARCHAR(1000) = NULL
|
|
AS
|
|
/*=============================================================================
|
|
|
|
Explication du traitement realise par la SP
|
|
-------------------------------------------
|
|
Cette SP sert a initialiser le status des jobs
|
|
|
|
Contexte d'utilisation
|
|
----------------------
|
|
Appelée à la main en passant le nom du job à initialiser si besoin sinon all jobs
|
|
|
|
Parametres
|
|
----------
|
|
@in_debug : non utilisé
|
|
@in_JobName : nom du job (si null All jobs)
|
|
|
|
Creation : 13.07.23 / FLA
|
|
|
|
Modifications :
|
|
|
|
=============================================================================*/
|
|
|
|
SET NOCOUNT ON;
|
|
|
|
/*------------------- Declaration des variables --------------------*/
|
|
DECLARE @JobName VARCHAR(255),
|
|
@LastStatus TINYINT,
|
|
@LastMessage NVARCHAR(4000),
|
|
@NextRun DATETIME,
|
|
@ID INT;
|
|
|
|
/*------------ Affectation des parametres aux variables ------------*/
|
|
|
|
/*-------------------------- Traitement ---------------------------*/
|
|
BEGIN TRY
|
|
|
|
DECLARE c_Jobs CURSOR FAST_FORWARD READ_ONLY FOR
|
|
SELECT SJ.name,
|
|
SJH.LastStatus,
|
|
SJH.Lastmessage,
|
|
SJA.NextRun
|
|
FROM msdb.dbo.sysjobs SJ
|
|
OUTER APPLY ( SELECT TOP 1 NextRun = JA.next_scheduled_run_date
|
|
FROM msdb.dbo.sysjobactivity JA
|
|
WHERE JA.job_id = SJ.job_id
|
|
ORDER BY session_id DESC) AS SJA
|
|
OUTER APPLY ( SELECT TOP 1 LastStatus = MIN(run_status),
|
|
Lastmessage = CASE
|
|
WHEN JH.sql_severity > 0 THEN message
|
|
ELSE NULL END
|
|
FROM msdb.dbo.sysjobhistory JH
|
|
WHERE JH.job_id = SJ.job_id
|
|
AND JH.run_date = ( SELECT MAX(T.run_date)
|
|
FROM msdb.dbo.sysjobhistory T
|
|
WHERE T.job_id = JH.job_id)
|
|
AND JH.run_time >= ( SELECT MAX(T.run_time)
|
|
FROM msdb.dbo.sysjobhistory T
|
|
WHERE T.job_id = JH.job_id
|
|
AND JH.run_date = T.run_date
|
|
AND T.step_id = 0)
|
|
GROUP BY CASE
|
|
WHEN JH.sql_severity > 0 THEN message
|
|
ELSE NULL END
|
|
ORDER BY MIN(run_status)) AS SJH
|
|
WHERE SJ.enabled = 1
|
|
AND (( SJ.name LIKE 'DR[0-9]%'
|
|
OR SJ.name LIKE 'D[0-9]%'
|
|
OR SJ.name LIKE 'M[0-9]%'
|
|
OR SJ.name LIKE 'W[0-9]%'
|
|
OR SJ.name LIKE '[_]%') AND @in_JobName IS NULL)
|
|
AND SJ.name NOT LIKE '%Log reader%'
|
|
OR (SJ.name = @in_JobName AND @in_JobName IS NOT NULL)
|
|
|
|
ORDER BY SJ.name;
|
|
|
|
|
|
OPEN c_Jobs;
|
|
|
|
FETCH NEXT FROM c_Jobs
|
|
INTO @JobName,
|
|
@LastStatus,
|
|
@LastMessage,
|
|
@NextRun;
|
|
|
|
WHILE @@FETCH_STATUS = 0
|
|
BEGIN
|
|
|
|
IF NOT EXISTS ( SELECT 1
|
|
FROM mon.Job_monitoring_config
|
|
WHERE JMC_name = @JobName)
|
|
BEGIN
|
|
|
|
INSERT INTO mon.Job_monitoring_config (JMC_name,
|
|
JMC_need_history)
|
|
VALUES (@JobName, CASE
|
|
WHEN @JobName LIKE '[_][0-9]%' THEN 0
|
|
WHEN @JobName LIKE 'DR[0-9]%' THEN 0
|
|
ELSE 1 END);
|
|
SELECT @ID = SCOPE_IDENTITY();
|
|
INSERT INTO mon.Job_monitoring_history (JMH_job_monitoring_config_ID,
|
|
JMH_next_schedule,
|
|
JMH_monitoring_status,
|
|
JMH_job_status,
|
|
JMH_error_message)
|
|
VALUES (@ID, @NextRun, CASE WHEN ISNULL(@LastStatus,1) = 1 THEN 0 ELSE 1 END, @LastStatus, @LastMessage);
|
|
|
|
END;
|
|
FETCH NEXT FROM c_Jobs
|
|
INTO @JobName,
|
|
@LastStatus,
|
|
@LastMessage,
|
|
@NextRun;
|
|
|
|
UPDATE JMC
|
|
SET JMC.JMC_Caller = SJ.name
|
|
FROM msdb.dbo.sysjobs SJ
|
|
INNER JOIN msdb.dbo.sysjobsteps SJS
|
|
ON SJ.job_id = SJS.job_id
|
|
INNER JOIN mon.Job_monitoring_config JMC
|
|
ON JMC.JMC_name = REPLACE(REPLACE(SUBSTRING(SJS.step_name, 11, 80), '[', ''), ']', '')
|
|
WHERE SJS.command LIKE '%aps_Launch_Job_SQL_Agent%'
|
|
OR SJS.command LIKE '%aps_CheckProd_Job%';
|
|
|
|
END;
|
|
|
|
CLOSE c_Jobs;
|
|
DEALLOCATE c_Jobs;
|
|
|
|
END TRY
|
|
BEGIN CATCH
|
|
|
|
/* Traitement des erreurs (sans RaiseError) */
|
|
EXEC dbo.get_Error_Info @in_RaiseError = 0;
|
|
|
|
END CATCH;
|
|
|
|
/*------------------ Retour au programme appelant -----------------*/
|
|
RETURN (@@error);
|
|
GO
|
|
|
|
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[GetNextScheduleForJob]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
|
|
DROP FUNCTION [dbo].[GetNextScheduleForJob]
|
|
GO
|
|
|
|
CREATE FUNCTION [dbo].[GetNextScheduleForJob]
|
|
(
|
|
@JobName SYSNAME,
|
|
@startDate DATETIME,
|
|
@endDate DATETIME
|
|
)
|
|
|
|
RETURNS @t TABLE (
|
|
scheduleID INT NOT NULL,
|
|
jobName SYSNAME NOT NULL,
|
|
jobDescription NVARCHAR(512) NOT NULL,
|
|
scheduleName SYSNAME NOT NULL,
|
|
categoryName SYSNAME NOT NULL,
|
|
startDate DATETIME NOT NULL,
|
|
jobEnabled INT NOT NULL,
|
|
scheduleEnabled INT NOT NULL)
|
|
|
|
AS
|
|
|
|
BEGIN
|
|
|
|
-- Create a tally table. If you already have one of your own please use that instead.
|
|
DECLARE @tallyNumbers TABLE
|
|
(
|
|
num SMALLINT PRIMARY KEY CLUSTERED
|
|
)
|
|
|
|
DECLARE @index SMALLINT
|
|
|
|
SET @index = 1
|
|
|
|
WHILE @index <= 8640
|
|
BEGIN
|
|
INSERT @tallyNumbers
|
|
(
|
|
num
|
|
)
|
|
VALUES (
|
|
@index
|
|
)
|
|
|
|
SET @index = @index + 1
|
|
END
|
|
|
|
-- Create a staging table for jobschedules
|
|
DECLARE @jobSchedules TABLE
|
|
(
|
|
rowID INT IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
|
|
jobName SYSNAME NOT NULL,
|
|
jobDescription NVARCHAR(512) NOT NULL,
|
|
scheduleName SYSNAME NOT NULL,
|
|
scheduleID INT NOT NULL,
|
|
categoryName SYSNAME NOT NULL,
|
|
freq_type INT NOT NULL,
|
|
freq_interval INT NOT NULL,
|
|
freq_subday_type INT NOT NULL,
|
|
freq_subday_interval INT NOT NULL,
|
|
freq_relative_interval INT NOT NULL,
|
|
freq_recurrence_factor INT NOT NULL,
|
|
startDate DATETIME NOT NULL,
|
|
startTime DATETIME NOT NULL,
|
|
endDate DATETIME NOT NULL,
|
|
endTime DATETIME NOT NULL,
|
|
jobEnabled INT NOT NULL,
|
|
scheduleEnabled INT NOT NULL
|
|
)
|
|
|
|
|
|
-- Populate the staging table for JobSchedules with SQL Server 2005 and SQL Server 2008
|
|
INSERT @JobSchedules
|
|
(
|
|
jobName,
|
|
jobDescription,
|
|
scheduleName,
|
|
scheduleID,
|
|
categoryName,
|
|
freq_type,
|
|
freq_interval,
|
|
freq_subday_type,
|
|
freq_subday_interval,
|
|
freq_relative_interval,
|
|
freq_recurrence_factor,
|
|
startDate,
|
|
startTime,
|
|
endDate,
|
|
endTime,
|
|
jobEnabled,
|
|
scheduleEnabled
|
|
)
|
|
SELECT sj.name,
|
|
COALESCE(sj.description, ''),
|
|
ss.name,
|
|
ss.schedule_id,
|
|
sc.name,
|
|
ss.freq_type,
|
|
ss.freq_interval,
|
|
ss.freq_subday_type,
|
|
ss.freq_subday_interval,
|
|
ss.freq_relative_interval,
|
|
ss.freq_recurrence_factor,
|
|
COALESCE(STR(ss.active_start_date, 8), CONVERT(CHAR(8), GETDATE(), 112)) startDate,
|
|
STUFF(STUFF(REPLACE(STR(ss.active_start_time, 6), ' ', '0'), 3, 0, ':'), 6, 0, ':') startTime,
|
|
STR(ss.active_end_date, 8) endDate,
|
|
STUFF(STUFF(REPLACE(STR(ss.active_end_time, 6), ' ', '0'), 3, 0, ':'), 6, 0, ':') endTime,
|
|
sj.enabled,
|
|
ss.enabled
|
|
FROM msdb..sysschedules AS ss WITH (NOLOCK)
|
|
INNER JOIN msdb..sysjobschedules AS sjs WITH (NOLOCK) ON sjs.schedule_id = ss.schedule_id
|
|
INNER JOIN msdb..sysjobs AS sj WITH (NOLOCK) ON sj.job_id = sjs.job_id
|
|
INNER JOIN msdb..syscategories AS sc WITH (NOLOCK) ON sc.category_id = sj.category_id
|
|
WHERE ss.freq_type IN (1, 4, 8, 16, 32)
|
|
AND sj.name = @JobName
|
|
|
|
-- Deal with first, second, third, fourth and last occurence
|
|
DECLARE @tempStart DATETIME,
|
|
@tempEnd DATETIME
|
|
|
|
SELECT @tempStart = DATEADD(MONTH, DATEDIFF(MONTH, '19000101', @startDate), '19000101'),
|
|
@TempEnd = DATEADD(MONTH, DATEDIFF(MONTH, '18991231', @endDate), '18991231')
|
|
|
|
DECLARE @dayInformation TABLE
|
|
(
|
|
infoDate DATETIME PRIMARY KEY CLUSTERED,
|
|
weekdayName VARCHAR(9) NOT NULL,
|
|
statusCode INT NOT NULL,
|
|
lastDay TINYINT DEFAULT 0
|
|
)
|
|
|
|
WHILE @tempStart <= @tempEnd
|
|
BEGIN
|
|
INSERT @dayInformation
|
|
(
|
|
infoDate,
|
|
weekdayName,
|
|
statusCode
|
|
)
|
|
SELECT @tempStart,
|
|
DATENAME(WEEKDAY, @tempStart),
|
|
CASE
|
|
WHEN DATEPART(DAY, @tempStart) BETWEEN 1 AND 7 THEN 1
|
|
WHEN DATEPART(DAY, @tempStart) BETWEEN 8 AND 14 THEN 2
|
|
WHEN DATEPART(DAY, @tempStart) BETWEEN 15 AND 21 THEN 4
|
|
WHEN DATEPART(DAY, @tempStart) BETWEEN 22 AND 28 THEN 8
|
|
ELSE 0
|
|
END
|
|
|
|
SET @tempStart = DATEADD(DAY, 1, @tempStart)
|
|
END
|
|
|
|
UPDATE di
|
|
SET di.statusCode = di.statusCode + 16
|
|
FROM @dayInformation AS di
|
|
INNER JOIN (
|
|
SELECT DATEDIFF(MONTH, '19000101', infoDate) AS theMonth,
|
|
DATEPART(DAY, MAX(infoDate)) - 6 AS theDay
|
|
FROM @dayInformation
|
|
GROUP BY DATEDIFF(MONTH, '19000101', infoDate)
|
|
) AS x ON x.theMonth = DATEDIFF(MONTH, '19000101', di.infoDate)
|
|
WHERE DATEPART(DAY, di.infoDate) >= x.theDay
|
|
|
|
UPDATE di
|
|
SET di.lastDay = 16
|
|
FROM @dayInformation AS di
|
|
INNER JOIN (
|
|
SELECT DATEDIFF(MONTH, '19000101', infoDate) AS theMonth,
|
|
MAX(infoDate) AS theDay
|
|
FROM @dayInformation
|
|
GROUP BY DATEDIFF(MONTH, '19000101', infoDate)
|
|
) AS x ON x.theMonth = DATEDIFF(MONTH, '19000101', di.infoDate)
|
|
WHERE di.infoDate = x.theDay
|
|
|
|
UPDATE @dayInformation
|
|
SET lastDay = DATEPART(DAY, infoDate)
|
|
WHERE DATEPART(DAY, infoDate) BETWEEN 1 AND 4
|
|
|
|
-- Stage all individual schedule times
|
|
DECLARE @scheduleTimes TABLE
|
|
(
|
|
rowID INT NOT NULL,
|
|
startDate DATETIME NOT NULL,
|
|
endDate DATETIME NOT NULL,
|
|
waitSeconds INT DEFAULT 0
|
|
)
|
|
|
|
-- Insert one time only schedules
|
|
INSERT @scheduleTimes
|
|
(
|
|
rowID,
|
|
startDate,
|
|
endDate
|
|
)
|
|
SELECT rowID,
|
|
startDate+startTime,
|
|
startDate+startTime
|
|
FROM @jobSchedules
|
|
WHERE freq_type = 1
|
|
AND startDate+startTime BETWEEN @StartDate AND @EndDate
|
|
|
|
-- Insert daily schedules
|
|
INSERT @scheduleTimes
|
|
(
|
|
rowID,
|
|
startDate,
|
|
endDate,
|
|
waitSeconds
|
|
)
|
|
SELECT js.rowID,
|
|
di.infoDate+js.startTime,
|
|
di.infoDate+js.endTime,
|
|
CASE js.freq_subday_type
|
|
WHEN 1 THEN 0
|
|
WHEN 2 THEN js.freq_subday_interval
|
|
WHEN 4 THEN 60 * js.freq_subday_interval
|
|
WHEN 8 THEN 3600 * js.freq_subday_interval
|
|
END
|
|
FROM @jobSchedules AS js
|
|
INNER JOIN @dayInformation AS di ON di.infoDate >= js.startDate
|
|
AND di.infoDate <= js.endDate
|
|
WHERE js.freq_type = 4
|
|
AND DATEDIFF(DAY, js.startDate, di.infoDate) % js.freq_interval = 0
|
|
|
|
|
|
-- Insert weekly schedules
|
|
INSERT @scheduleTimes
|
|
(
|
|
rowID,
|
|
startDate,
|
|
endDate,
|
|
waitSeconds
|
|
)
|
|
SELECT js.rowID,
|
|
di.infoDate+js.startTime,
|
|
di.infoDate+js.endTime,
|
|
CASE js.freq_subday_type
|
|
WHEN 1 THEN 0
|
|
WHEN 2 THEN js.freq_subday_interval
|
|
WHEN 4 THEN 60 * js.freq_subday_interval
|
|
WHEN 8 THEN 3600 * js.freq_subday_interval
|
|
END
|
|
FROM @jobSchedules AS js
|
|
INNER JOIN @dayInformation AS di ON di.infoDate >= js.startDate
|
|
AND di.infoDate <= js.endDate
|
|
WHERE js.freq_type = 8
|
|
AND 1 = CASE
|
|
WHEN js.freq_interval & 1 = 1 AND di.weekdayName = 'Sunday' THEN 1
|
|
WHEN js.freq_interval & 2 = 2 AND di.weekdayName = 'Monday' THEN 1
|
|
WHEN js.freq_interval & 4 = 4 AND di.weekdayName = 'Tuesday' THEN 1
|
|
WHEN js.freq_interval & 8 = 8 AND di.weekdayName = 'Wednesday' THEN 1
|
|
WHEN js.freq_interval & 16 = 16 AND di.weekdayName = 'Thursday' THEN 1
|
|
WHEN js.freq_interval & 32 = 32 AND di.weekdayName = 'Friday' THEN 1
|
|
WHEN js.freq_interval & 64 = 64 AND di.weekdayName = 'Saturday' THEN 1
|
|
ELSE 0
|
|
END
|
|
AND (DATEDIFF(DAY, js.startDate, di.infoDate) / 7) % js.freq_recurrence_factor = 0
|
|
|
|
-- Insert monthly schedules
|
|
INSERT @scheduleTimes
|
|
(
|
|
rowID,
|
|
startDate,
|
|
endDate,
|
|
waitSeconds
|
|
)
|
|
SELECT js.rowID,
|
|
di.infoDate+js.startTime,
|
|
di.infoDate+js.endTime,
|
|
CASE js.freq_subday_type
|
|
WHEN 1 THEN 0
|
|
WHEN 2 THEN js.freq_subday_interval
|
|
WHEN 4 THEN 60 * js.freq_subday_interval
|
|
WHEN 8 THEN 3600 * js.freq_subday_interval
|
|
END
|
|
FROM @jobSchedules AS js
|
|
INNER JOIN @dayInformation AS di ON di.infoDate >= js.startDate
|
|
AND di.infoDate <= js.endDate
|
|
WHERE js.freq_type = 16
|
|
AND DATEPART(DAY, di.infoDate) = js.freq_interval
|
|
AND DATEDIFF(MONTH, js.startDate, di.infoDate) % js.freq_recurrence_factor = 0
|
|
|
|
-- Insert monthly relative schedules
|
|
INSERT @scheduleTimes
|
|
(
|
|
rowID,
|
|
startDate,
|
|
endDate,
|
|
waitSeconds
|
|
)
|
|
SELECT js.rowID,
|
|
di.infoDate+js.startTime,
|
|
di.infoDate+js.endTime,
|
|
CASE js.freq_subday_type
|
|
WHEN 1 THEN 0
|
|
WHEN 2 THEN js.freq_subday_interval
|
|
WHEN 4 THEN 60 * js.freq_subday_interval
|
|
WHEN 8 THEN 3600 * js.freq_subday_interval
|
|
END
|
|
FROM @jobSchedules AS js
|
|
INNER JOIN @dayInformation AS di ON di.infoDate >= js.startDate
|
|
AND di.infoDate <= js.endDate
|
|
WHERE js.freq_type = 32
|
|
AND 1 = CASE
|
|
WHEN js.freq_interval = 1 AND di.weekdayName = 'Sunday' THEN 1
|
|
WHEN js.freq_interval = 2 AND di.weekdayName = 'Monday' THEN 1
|
|
WHEN js.freq_interval = 3 AND di.weekdayName = 'Tuesday' THEN 1
|
|
WHEN js.freq_interval = 4 AND di.weekdayName = 'Wednesday' THEN 1
|
|
WHEN js.freq_interval = 5 AND di.weekdayName = 'Thursday' THEN 1
|
|
WHEN js.freq_interval = 6 AND di.weekdayName = 'Friday' THEN 1
|
|
WHEN js.freq_interval = 7 AND di.weekdayName = 'Saturday' THEN 1
|
|
WHEN js.freq_interval = 8 AND js.freq_relative_interval = di.lastDay THEN 1
|
|
WHEN js.freq_interval = 9 AND di.weekdayName NOT IN ('Sunday', 'Saturday') THEN 1
|
|
WHEN js.freq_interval = 10 AND di.weekdayName IN ('Sunday', 'Saturday') THEN 1
|
|
ELSE 0
|
|
END
|
|
AND di.statusCode & js.freq_relative_interval = js.freq_relative_interval
|
|
AND DATEDIFF(MONTH, js.startDate, di.infoDate) % js.freq_recurrence_factor = 0
|
|
|
|
-- Get the daily recurring schedule times
|
|
INSERT @scheduleTimes
|
|
(
|
|
rowID,
|
|
startDate,
|
|
endDate,
|
|
waitSeconds
|
|
)
|
|
SELECT st.rowID,
|
|
DATEADD(SECOND, tn.num * st.waitSeconds, st.startDate),
|
|
st.endDate,
|
|
st.waitSeconds
|
|
FROM @scheduleTimes AS st
|
|
CROSS JOIN @tallyNumbers AS tn
|
|
WHERE tn.num * st.waitSeconds <= DATEDIFF(SECOND, st.startDate, st.endDate)
|
|
AND st.waitSeconds > 0
|
|
|
|
-- Present the result
|
|
INSERT @t (scheduleID,
|
|
jobName,
|
|
jobDescription,
|
|
scheduleName,
|
|
categoryName,
|
|
startDate,
|
|
jobEnabled,
|
|
scheduleEnabled)
|
|
SELECT js.scheduleID,
|
|
js.jobName,
|
|
js.jobDescription,
|
|
js.scheduleName,
|
|
js.categoryName,
|
|
st.startDate,
|
|
js.jobEnabled,
|
|
js.scheduleEnabled
|
|
FROM @scheduleTimes AS st
|
|
INNER JOIN @jobSchedules AS js ON js.rowID = st.rowID
|
|
WHERE js.jobEnabled = 1
|
|
AND js.scheduleEnabled = 1
|
|
AND st.startDate >= @startDate
|
|
AND st.startDate <= @endDate
|
|
RETURN
|
|
|
|
END
|
|
GO
|
|
|
|
|
|
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mon].[Maj_Jobs_Status]') AND type IN (N'P', N'PC'))
|
|
DROP PROCEDURE [mon].[Maj_Jobs_Status]
|
|
GO
|
|
|
|
CREATE PROCEDURE [mon].[Maj_Jobs_Status]
|
|
@in_debug TINYINT = 0,
|
|
@in_JobName NVARCHAR(1000) = NULL,
|
|
@in_JobID UNIQUEIDENTIFIER = NULL
|
|
AS
|
|
/*=============================================================================
|
|
|
|
Explication du traitement realise par la SP
|
|
-------------------------------------------
|
|
Cette SP sert a mettre à jour le status des jobs
|
|
|
|
Contexte d'utilisation
|
|
----------------------
|
|
Appelée depuis le step Empty Step et Send mail KO des jobs
|
|
|
|
Parametres
|
|
----------
|
|
@in_debug : non utilisé
|
|
@in_JobName : nom du job (si null All jobs)
|
|
|
|
Creation : 03.08.23 / FLA
|
|
|
|
Modifications :
|
|
22.08.23 : Get directly the job_id in job instead of put job name in parameter
|
|
21.09.23 : Call the new version of function [GetNextScheduleForJob]
|
|
|
|
=============================================================================*/
|
|
|
|
|
|
SET NOCOUNT ON;
|
|
|
|
/*------------------- Declaration des variables --------------------*/
|
|
DECLARE @LastMessage NVARCHAR(4000) = NULL,
|
|
@JMC_ID INT = 0,
|
|
@JMH_ID INT = NULL,
|
|
@NeedHistory BIT = 1,
|
|
@NextRun DATETIME
|
|
|
|
/*------------ Affectation des parametres aux variables ------------*/
|
|
|
|
/*-------------------------- Traitement ---------------------------*/
|
|
BEGIN TRY
|
|
|
|
IF @in_JobID IS NOT NULL
|
|
SELECT @in_JobName = name FROM msdb.dbo.sysjobs WHERE job_id = @in_JobID
|
|
|
|
SELECT @LastMessage = jh.message
|
|
FROM msdb.dbo.sysjobhistory jh
|
|
INNER JOIN msdb.dbo.sysjobactivity ja
|
|
ON ja.job_id = jh.job_id
|
|
INNER JOIN msdb.dbo.sysjobs j
|
|
ON j.job_id = ja.job_id
|
|
WHERE j.name = @in_JobName
|
|
AND run_status = 0 --and ja.stop_execution_date is null--
|
|
AND ja.session_id = (SELECT TOP 1 session_id
|
|
FROM msdb.dbo.syssessions
|
|
ORDER BY agent_start_date DESC)
|
|
AND start_execution_date IS NOT NULL
|
|
--AND stop_execution_date is null
|
|
AND msdb.dbo.agent_datetime(run_date, run_time) >= start_execution_date;
|
|
|
|
/* Gestion des Query Timeout Error */
|
|
IF EXISTS (SELECT 1
|
|
FROM msdb..sysjobhistory jh
|
|
INNER JOIN msdb..sysjobactivity ja
|
|
ON ja.job_id = jh.job_id
|
|
INNER JOIN msdb..sysjobs j
|
|
ON j.job_id = ja.job_id
|
|
WHERE j.name = @in_JobName
|
|
AND run_status = 1 --and ja.stop_execution_date is null--
|
|
AND ja.session_id = (SELECT TOP 1 session_id
|
|
FROM msdb.dbo.syssessions
|
|
ORDER BY agent_start_date DESC)
|
|
AND start_execution_date IS NOT NULL
|
|
AND jh.sql_message_id = 7412
|
|
AND msdb.dbo.agent_datetime(run_date, run_time) >= start_execution_date)
|
|
BEGIN
|
|
|
|
SELECT @LastMessage = jh.message
|
|
FROM msdb..sysjobhistory jh
|
|
INNER JOIN msdb..sysjobactivity ja
|
|
ON ja.job_id = jh.job_id
|
|
INNER JOIN msdb..sysjobs j
|
|
ON j.job_id = ja.job_id
|
|
WHERE j.name = @in_JobName
|
|
AND run_status = 1 --and ja.stop_execution_date is null--
|
|
AND ja.session_id = (SELECT TOP 1 session_id
|
|
FROM msdb.dbo.syssessions
|
|
ORDER BY agent_start_date DESC)
|
|
AND start_execution_date IS NOT NULL
|
|
AND jh.sql_message_id = 7412
|
|
AND msdb.dbo.agent_datetime(run_date, run_time) >= start_execution_date;
|
|
END;
|
|
|
|
SELECT @JMC_ID = JMC.Job_monitoring_config_ID,
|
|
@NeedHistory = JMC.JMC_need_history,
|
|
@JMH_ID = JMH.Job_monitoring_history_ID
|
|
FROM [mon].[Job_monitoring_config] JMC
|
|
LEFT OUTER JOIN [mon].[Job_monitoring_history] JMH
|
|
ON JMC.Job_monitoring_config_ID = JMH.JMH_job_monitoring_config_ID
|
|
WHERE JMC_name = @in_JobName
|
|
AND JMC_ignore = 0
|
|
|
|
IF @JMC_ID <> 0
|
|
BEGIN
|
|
|
|
SELECT @NextRun = Job.startDate FROM
|
|
(SELECT TOP 1 startDate
|
|
FROM [dbo].[GetNextScheduleForJob](@in_JobName,GETDATE(), GETDATE() + 1)
|
|
ORDER BY startDate) AS Job
|
|
|
|
IF @NeedHistory = 0
|
|
BEGIN
|
|
UPDATE [mon].[Job_monitoring_history] SET [JMH_next_schedule] = @NextRun,
|
|
[JMH_monitoring_status] = CASE WHEN @LastMessage IS NOT NULL THEN 1 ELSE 0 END,
|
|
[JMH_job_status] = CASE WHEN @LastMessage IS NOT NULL THEN 0 ELSE 1 END,
|
|
[JMH_error_message] = @LastMessage,
|
|
[JMH_update_status] = GETDATE()
|
|
WHERE JMH_job_monitoring_config_ID = @JMH_ID
|
|
END
|
|
ELSE
|
|
BEGIN
|
|
INSERT INTO [mon].[Job_monitoring_history] ([JMH_job_monitoring_config_ID],
|
|
[JMH_next_schedule],
|
|
[JMH_monitoring_status],
|
|
[JMH_job_status],
|
|
[JMH_error_message],
|
|
[JMH_update_status])
|
|
VALUES (@JMC_ID,
|
|
@NextRun,
|
|
CASE WHEN @LastMessage IS NOT NULL THEN 1 ELSE 0 END,
|
|
CASE WHEN @LastMessage IS NOT NULL THEN 0 ELSE 1 END,
|
|
@LastMessage,
|
|
DEFAULT
|
|
)
|
|
END
|
|
END
|
|
|
|
END TRY
|
|
BEGIN CATCH
|
|
|
|
/* Traitement des erreurs (sans RaiseError) */
|
|
EXEC dbo.get_Error_Info @in_RaiseError = 0;
|
|
|
|
END CATCH;
|
|
|
|
/*------------------ Retour au programme appelant -----------------*/
|
|
RETURN (@@error);
|
|
GO
|
|
|
|
|
|
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mon].[Get_Jobs_Status]') AND type in (N'P', N'PC'))
|
|
DROP PROCEDURE [mon].[Get_Jobs_Status]
|
|
GO
|
|
|
|
CREATE PROCEDURE [mon].[Get_Jobs_Status]
|
|
@in_debug TINYINT = 0,
|
|
@in_JobName NVARCHAR(1000) = NULL
|
|
AS
|
|
/*=============================================================================
|
|
|
|
Explication du traitement realise par la SP
|
|
-------------------------------------------
|
|
Cette SP sert à retourner le status des jobs
|
|
|
|
Contexte d'utilisation
|
|
----------------------
|
|
Appelée depuis le MDV ou à la main
|
|
|
|
Parametres
|
|
----------
|
|
@in_debug : non utilisé
|
|
@in_JobName : nom du job (si null All jobs)
|
|
|
|
Creation : 17.08.23 / FLA
|
|
|
|
Modifications :
|
|
|
|
=============================================================================*/
|
|
|
|
|
|
SET NOCOUNT ON;
|
|
|
|
/*------------------- Declaration des variables --------------------*/
|
|
|
|
|
|
/*------------ Affectation des parametres aux variables ------------*/
|
|
|
|
/*-------------------------- Traitement ---------------------------*/
|
|
BEGIN TRY
|
|
|
|
SELECT JMC.JMC_name AS JobName,
|
|
JMH.JMH_error_message AS Error,
|
|
CASE
|
|
WHEN ( JMH.JMH_job_status = 0
|
|
AND JMH_monitoring_status = 1) THEN 'ERROR'
|
|
WHEN (CASE WHEN ISNULL(JMH.JMH_next_schedule,T1.JMH_next_schedule) < ISNULL(T1.JMH_next_schedule,JMH.JMH_next_schedule) THEN ISNULL(JMH.JMH_next_schedule,T1.JMH_next_schedule) ELSE ISNULL(T1.JMH_next_schedule,JMH.JMH_next_schedule) END < GETDATE()) THEN 'NOT EXECUTED'
|
|
ELSE '' END AS Status
|
|
FROM mon.Job_monitoring_config JMC
|
|
INNER JOIN mon.Job_monitoring_history JMH
|
|
ON JMC.Job_monitoring_config_ID = JMH.JMH_job_monitoring_config_ID
|
|
AND JMC.JMC_ignore = 0
|
|
AND JMH.JMH_update_status = (SELECT MAX(JMH2.JMH_update_status)
|
|
FROM mon.Job_monitoring_history JMH2
|
|
WHERE JMH2.JMH_job_monitoring_config_ID = JMC.Job_monitoring_config_ID)
|
|
OUTER APPLY (SELECT JMH3.JMH_next_schedule FROM mon.Job_monitoring_config JMC3
|
|
INNER JOIN mon.Job_monitoring_history JMH3
|
|
ON JMC3.Job_monitoring_config_ID = JMH3.JMH_job_monitoring_config_ID
|
|
AND JMH3.JMH_update_status = (SELECT MAX(JMH4.JMH_update_status)
|
|
FROM mon.Job_monitoring_history JMH4
|
|
WHERE JMH4.JMH_job_monitoring_config_ID = JMC3.Job_monitoring_config_ID)
|
|
WHERE JMC3.JMC_name = JMC.JMC_caller) AS T1
|
|
WHERE JMC.JMC_name = COALESCE(@in_JobName, JMC.JMC_name)
|
|
ORDER BY JMC.JMC_name
|
|
|
|
END TRY
|
|
BEGIN CATCH
|
|
|
|
/* Traitement des erreurs (sans RaiseError) */
|
|
EXEC dbo.get_Error_Info @in_RaiseError = 0;
|
|
|
|
END CATCH;
|
|
|
|
/*------------------ Retour au programme appelant -----------------*/
|
|
RETURN (@@error);
|
|
GO
|
|
|
|
|
|
/***********************************************************************/
|
|
/* INITIALISATION */
|
|
/* */
|
|
/***********************************************************************/
|
|
|
|
EXEC [mon].[Initialize_Jobs_Status]
|
|
|
|
SELECT *
|
|
FROM mon.Job_monitoring_config JMC
|
|
INNER JOIN mon.Job_monitoring_history JMH
|
|
ON JMC.Job_monitoring_config_ID = JMH.JMH_Job_monitoring_config_ID
|
|
ORDER BY JMC.JMC_name
|
|
|
|
|
|
EXEC [mon].[Get_Jobs_Status]
|