Files
sql-scripts/TPDT-268 - ACP in task sequence/dba_packages/DeployTriggerDDLAudit.sql
2024-03-07 16:52:14 +01:00

582 lines
17 KiB
Transact-SQL

/*=============================================================================
Explication du traitement realise par le script SQL pour creer un trigger
capturant les evenements DDL specifies
---------------------------------------------------
1. Creation du schema [dba]
2. Creation de la table [DDL_audit]
3. Authorisations de la table [DDL_audit]
4. Creation du trigger [tDDL_Capture_DDL_Events]
5. Activation du trigger [tDDL_Capture_DDL_Events]
6. Création de la table "SQL_Errors"
7. Création de la SP "get_Error_Info"
8. Création de la SP "Purge_DDL_audit"
9. Création de la catégorie "DBA-Maintenance"
10. Création du job de l'agent SQL "D93110 - Purge DDL audit"
Creation : 12.08.2016 / LPE
Modifications : 17.03.2022 - FLA : Change DBA mail
18.01.2023 - SPE : Mise en place d une nouvelle colonne datetime2
=============================================================================*/
/****************************************************************/
/************** CREATION DU SCHEMA [dba] ****************/
/****************************************************************/
USE [master]
GO
IF NOT EXISTS (SELECT * FROM master.sys.schemas WHERE name = N'dba')
BEGIN
EXEC('CREATE SCHEMA [dba] AUTHORIZATION [dbo]')
END
GO
/****************************************************************/
/********** CREATION DE LA TABLE [DDL_audit] ************/
/****************************************************************/
USE [master]
GO
IF NOT EXISTS (SELECT * FROM master.sys.objects WHERE object_id = OBJECT_ID(N'[dba].[DDL_audit]') AND type in (N'U'))
BEGIN
CREATE TABLE [master].[dba].[DDL_audit](
[DA_DDL_audit_ID] [bigint] IDENTITY(1,1) NOT NULL,
[DA_Event_Xml] [xml] NULL,
[DA_App_Name] [nvarchar](128) NULL,
[DA_Host_Name] [nvarchar](128) NULL,
[DA_Create_Date] [datetime2](0) NOT NULL CONSTRAINT DF_DA_Create_Date DEFAULT GETDATE(),
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE OBJECT_NAME(object_id) = 'DDL_audit' AND name = 'DA_Create_Date')
BEGIN
ALTER TABLE [master].[dba].[DDL_audit] ADD [DA_Create_Date] [datetime2](0) NULL CONSTRAINT DF_DA_Create_Date DEFAULT GETDATE()
END
GO
IF EXISTS (SELECT TOP 1 1 FROM [master].[dba].[DDL_audit] WHERE [DA_Create_Date] IS NULL)
BEGIN
UPDATE [master].[dba].[DDL_audit] SET [DA_Create_Date] = DA_Event_Xml.value('(./EVENT_INSTANCE/PostTime)[1]','NVARCHAR(MAX)')
ALTER TABLE [master].[dba].[DDL_audit] ALTER COLUMN [DA_Create_Date] [datetime2](0) NOT NULL
END
GO
IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE name = 'NCIX_DDL_audit_COL_DA_Create_Date')
BEGIN
CREATE NONCLUSTERED INDEX [NCIX_DDL_audit_COL_DA_Create_Date] ON [dba].[DDL_audit]
(
[DA_Create_Date] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
END
GO
/****************************************************************/
/******* AUTHORISATIONS DE LA TABLE [DDL_audit] *********/
/****************************************************************/
USE [master]
GO
GRANT INSERT ON [master].[dba].[DDL_audit] TO [public] AS [dbo]
GO
/****************************************************************/
/**** CREATION DU TRIGGER [tDDL_Capture_DDL_Events] ****/
/****************************************************************/
USE [master]
GO
IF EXISTS (SELECT * FROM master.sys.server_triggers WHERE parent_class_desc = 'SERVER' AND name = N'tDDL_Capture_DDL_Events')
DROP TRIGGER [tDDL_Capture_DDL_Events] ON ALL SERVER
GO
CREATE TRIGGER [tDDL_Capture_DDL_Events]
ON ALL SERVER
FOR RENAME,
DDL_SERVER_LEVEL_EVENTS,
DDL_TABLE_EVENTS,
DDL_VIEW_EVENTS,
DDL_INDEX_EVENTS,
DDL_SYNONYM_EVENTS,
DDL_FUNCTION_EVENTS,
DDL_PROCEDURE_EVENTS,
DDL_TRIGGER_EVENTS,
DDL_EVENT_NOTIFICATION_EVENTS,
DDL_ASSEMBLY_EVENTS,
DDL_TYPE_EVENTS,
DDL_DATABASE_SECURITY_EVENTS,
DDL_SSB_EVENTS,
DDL_XML_SCHEMA_COLLECTION_EVENTS,
DDL_PARTITION_EVENTS,
DDL_DEFAULT_EVENTS,
DDL_EXTENDED_PROPERTY_EVENTS,
DDL_FULLTEXT_CATALOG_EVENTS,
DDL_PLAN_GUIDE_EVENTS,
DDL_RULE_EVENTS,
DDL_FULLTEXT_STOPLIST_EVENTS
AS
/*=============================================================================
DDL trigger capturing listed DDL Events
List of available DDL Events:
----------------------------
WITH DirectReports(name, parent_type, type, level, sort) AS
(
SELECT CONVERT(varchar(255),type_name),
parent_type,
type,
1,
CONVERT(varchar(255),type_name)
FROM sys.trigger_event_types
WHERE parent_type IS NULL
UNION ALL
SELECT CONVERT(varchar(255), REPLICATE ('| ' , level) + e.type_name),
e.parent_type,
e.type,
level + 1,
CONVERT (varchar(255), RTRIM(sort) + '| ' + e.type_name)
FROM sys.trigger_event_types AS e
INNER JOIN DirectReports AS d
ON d.type = e.parent_type
)
SELECT parent_type,
type,
name
FROM DirectReports
ORDER BY sort;
Creation : 12.08.16 / LPE
Modifications :
DD.MM.YY / xxx :
=============================================================================*/
SET NOCOUNT ON;
INSERT [master].[dba].[DDL_audit]
(DA_Event_Xml,
DA_App_Name,
DA_Host_Name)
SELECT EVENTDATA(),
APP_NAME(),
HOST_NAME();
GO
/****************************************************************/
/**** ACTIVATION DU TRIGGER [tDDL_Capture_DDL_Events] ****/
/****************************************************************/
ENABLE TRIGGER [tDDL_Capture_DDL_Events] ON ALL SERVER
GO
/*****************************************************************/
/********* 9. CREATE Table "SQL_Errors" **************************/
/*****************************************************************/
USE [HCITools]
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SQL_Errors]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[SQL_Errors](
[ServerName] [nvarchar](50) NULL,
[AppName] [nvarchar](128) NULL,
[UserName] [sysname] NULL,
[ObjectName] [sysname] NULL,
[Date] [datetime] NULL,
[SourceType] [tinyint] NULL,
[ErrorMessage] [varchar](max) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
END
GO
/*****************************************************************/
/********* 10. CREATE SP "get_Error_Info" ************************/
/*****************************************************************/
SET ANSI_PADDING ON
GO
USE [HCITools]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_Error_Info]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[get_Error_Info]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[get_Error_Info]
@in_debug tinyint = 0,
@in_Recipients varchar(8000) = '',
@in_LogToTable tinyint = 0,
@in_Context tinyint = 1, -- 1 = SP, 2 = Job
@in_RaiseError tinyint = 1
AS
declare @ErrorMessage nvarchar(4000) = ERROR_MESSAGE(),
@ErrorNumber int = ERROR_NUMBER(),
@ErrorSeverity int = ERROR_SEVERITY(),
@ErrorState int = ERROR_STATE(),
@ErrorLine int = ERROR_LINE(),
@ErrorProc nvarchar(128) = COALESCE(ERROR_PROCEDURE(), 'Not within procedure'),
@Error varchar(max)
BEGIN TRY
select @Error = 'Error Number: ' + CAST(@ErrorNumber AS varchar(10)) + CHAR(13) +
'Error Message: ' + @ErrorMessage + CHAR(13) +
'Error Severity: ' + CAST(@ErrorSeverity AS varchar(10)) + CHAR(13) +
'Error State: ' + CAST(@ErrorState AS varchar(10)) + CHAR(13) +
'Error Line: ' + CAST(@ErrorLine AS varchar(10)) + CHAR(13) +
'Error Proc: ' + @ErrorProc + CHAR(13)
PRINT @Error
IF @in_Recipients <> ''
BEGIN
IF @in_Context = 1
exec dbo.aps_Send_Mail_with_template @in_job_type = 0,@in_param_message = @Error, @in_param_varchar_2 = @in_Recipients
ELSE
BEGIN
exec dbo.aps_Send_Mail_with_template @in_param_varchar_2 = @in_Recipients
END
END
IF @in_LogToTable = 1
INSERT INTO SQL_Errors VALUES (@@SERVERNAME,APP_NAME(),CURRENT_USER,@ErrorProc,GETDATE(),@in_Context,@Error)
END TRY
BEGIN CATCH
RAISERROR ('Erreur dans la SP [dbo].[get_Error_Info]',16,1)
RETURN
END CATCH
IF @in_RaiseError = 1
RAISERROR (@ErrorMessage,
@ErrorSeverity,
@ErrorState
);
GO
/*****************************************************************/
/********** 11. CREATE SP "Purge_DDL_audit" **********************/
/*****************************************************************/
USE [HCITools]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Purge_DDL_audit]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[Purge_DDL_audit]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[Purge_DDL_audit]
@in_NbDays int = 30,
@in_debug int = null
AS
/*=============================================================================
Explication du traitement realise par la SP
-------------------------------------------
Cette SP sert à supprimer les traces des evenements DDL de plus de XX jours
dans la table master.dba.DDL_audit
Contexte d'utilisation
----------------------
Cette SP est appelée par le job D93110 - Purge DDL audit
Parametres
----------
@in_NbDays : nombre de jours glissant à conserver (30 par défaut)
@in_debug : non utilisé
Creation : 12.08.16 / LPE
Modifications : 18.01.2023 - SPE: Delete avec l aide de la nouvelle colonne Datetime2 DA_Create_Date
=============================================================================*/
set nocount on;
declare @result_sp int,
@errno int,
@errmsg varchar(255)
/*------------------- Declaration des variables --------------------*/
/*------------ Affectation des parametres aux variables ------------*/
/*-------------------------- Traitement ---------------------------*/
BEGIN TRY
DELETE FROM master.dba.DDL_audit WHERE DA_Create_Date < DateAdd(dd,-@in_NbDays,getdate())
END TRY
BEGIN CATCH
/* Traitement des erreurs (avec RaiseError) */
EXEC dbo.get_Error_Info @in_RaiseError = 1
END CATCH
/*------------------ Retour au programme appelant -----------------*/
/*---------------------- Traitement des erreurs ----------------------*/
GO
/********************************************************************************/
/********* 12. CREATE SQL AGENT JOB CATEGORY "DBA-Maintenance" ******************/
/********************************************************************************/
USE [msdb]
GO
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'DBA-Maintenance' AND category_class=1)
BEGIN
EXEC msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'DBA-Maintenance'
END
/*****************************************************************************/
/********* 13. CREATE SQL AGENT JOB "D93110 - Purge DDL audit" *************/
/*****************************************************************************/
USE [msdb]
GO
/* Drop existing standard schedule for job */
declare @schedule_id int
declare c_schedules cursor local forward_only static for
select ss.schedule_id
from msdb.dbo.sysjobschedules sjs
INNER JOIN msdb.dbo.sysschedules ss
ON sjs.schedule_id = ss.schedule_id
AND ss.name NOT LIKE '%#SPEC#'
INNER JOIN msdb.dbo.sysjobs sj
ON sjs.job_id = sj.job_id
WHERE sj.name = N'D93110 - Purge DDL audit'
open c_schedules
FETCH NEXT FROM c_schedules into @schedule_id
while @@fetch_status = 0
begin
IF ((select COUNT(*) from msdb.dbo.sysjobschedules where schedule_id=@schedule_id) = 1)
EXEC msdb.dbo.sp_delete_schedule @schedule_id=@schedule_id, @force_delete = 1
FETCH NEXT FROM c_schedules into @schedule_id
end
close c_schedules
deallocate c_schedules
IF EXISTS (SELECT job_id FROM msdb.dbo.sysjobs_view WHERE name = N'D93110 - Purge DDL audit')
EXEC msdb.dbo.sp_delete_job @job_name = N'D93110 - Purge DDL audit', @delete_unused_schedule=0
GO
/* Creation Job and Steps*/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'DBA-Maintenance' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'DBA-Maintenance'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
END
/* Add Job */
DECLARE @jobId BINARY(16)
EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'D93110 - Purge DDL audit',
@enabled=1,
@notify_level_eventlog=0,
@notify_level_email=0,
@notify_level_netsend=0,
@notify_level_page=0,
@delete_level=0,
@description=N'Purge DDL Events History in table master.dba.DDL_audit',
@category_name=N'DBA-Maintenance',
@start_step_id=1,
@owner_login_name=N'sa', @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/* Add Step */
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'Empty step',
@step_id=1,
@cmdexec_success_code=0,
@on_success_action=3,
@on_success_step_id=0,
@on_fail_action=3,
@on_fail_step_id=0,
@retry_attempts=0,
@retry_interval=0,
@os_run_priority=0, @subsystem=N'TSQL',
@command=N'/* Empty step */',
@database_name=N'master',
@output_file_name=NULL,
@flags=0,
@database_user_name=NULL,
@server=NULL,
@additional_parameters=NULL,
@proxy_id=NULL,
@proxy_name=NULL
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/* Add Step */
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'Purge DDL audit',
@step_id=2,
@cmdexec_success_code=0,
@on_success_action=3,
@on_success_step_id=0,
@on_fail_action=4,
@on_fail_step_id=4,
@retry_attempts=0,
@retry_interval=1,
@os_run_priority=0, @subsystem=N'TSQL',
@command=N'exec [dbo].[Purge_DDL_audit] @in_NbDays = 30',
@database_name=N'HCITools',
@output_file_name=NULL,
@flags=0,
@database_user_name=NULL,
@server=NULL,
@additional_parameters=NULL,
@proxy_id=NULL,
@proxy_name=NULL
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/* Add Step */
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'Empty step for success',
@step_id=3,
@cmdexec_success_code=0,
@on_success_action=1,
@on_success_step_id=0,
@on_fail_action=4,
@on_fail_step_id=4,
@retry_attempts=0,
@retry_interval=0,
@os_run_priority=0, @subsystem=N'TSQL',
@command=N'/* Empty step */
exec Get_Job_Error_Info @in_JobName = ''D93110 - Purge DDL audit'', @in_Recipients = ''DBA_operator''',
@database_name=N'HCITools',
@output_file_name=NULL,
@flags=0,
@database_user_name=NULL,
@server=NULL,
@additional_parameters=NULL,
@proxy_id=NULL,
@proxy_name=NULL
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/* Add Step */
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'Send email KO',
@step_id=4,
@cmdexec_success_code=0,
@on_success_action=2,
@on_success_step_id=0,
@on_fail_action=2,
@on_fail_step_id=0,
@retry_attempts=0,
@retry_interval=0,
@os_run_priority=0, @subsystem=N'TSQL',
@command=N'exec Get_Job_Error_Info @in_JobName = ''D93110 - Purge DDL audit'', @in_Recipients = ''DBA_operator''',
@database_name=N'HCITools',
@output_file_name=NULL,
@flags=0,
@database_user_name=NULL,
@server=NULL,
@additional_parameters=NULL,
@proxy_id=NULL,
@proxy_name=NULL
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/* Add Standard Schedule */
EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'D93110-D',
@enabled=1,
@freq_type=4,
@freq_interval=1,
@freq_subday_type=1,
@freq_subday_interval=0,
@freq_relative_interval=0,
@freq_recurrence_factor=0,
@active_start_date=20151116,
@active_end_date=99991231,
@active_start_time=30000,
@active_end_time=235959
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/* Attach existing specific schedule for job */
declare @enabled_schedule int,
@schedule_name nvarchar(50)
declare c_schedules cursor local forward_only static for
select enabled, name
from msdb.dbo.sysschedules
where name LIKE 'D93110%'
and name LIKE '%#SPEC#'
open c_schedules
FETCH NEXT FROM c_schedules into @enabled_schedule, @schedule_name
while @@fetch_status = 0
begin
EXEC @ReturnCode = msdb.dbo.sp_attach_schedule @job_id = @jobId, @schedule_name=@schedule_name
IF(@enabled_schedule = 1)
begin
SET @schedule_name = SUBSTRING(@schedule_name,0,LEN(@schedule_name)-5)
IF EXISTS (select name from msdb.dbo.sysschedules where name = @schedule_name)
EXEC @ReturnCode = msdb.dbo.sp_update_schedule @name=@schedule_name, @enabled=0
end
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
FETCH NEXT FROM c_schedules into @enabled_schedule, @schedule_name
end
close c_schedules
deallocate c_schedules
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:
GO