Introduzione
Spesso è necessario informare in qualche modo gli amministratori sui problemi con un server. Le notifiche sono generalmente divise in 2 tipi:
1) notifiche in tempo reale, ovvero quelle che devono arrivare immediatamente quando si verifica un problema
2) notifiche ritardate, ovvero quelle che arrivano dopo un tempo abbastanza lungo (più di 1 ora) dal verificarsi di un problema.
Nel mio lavoro, era necessario estendere le funzionalità della normale posta elettronica di database di SQL Server.
In questo articolo considereremo un esempio di come generare notifiche nelle tabelle HTML e inviarle agli amministratori.
Soluzione
1. Configura Posta Database
2. Crea una tabella per i destinatari:
[expand title =”Codice”]
USE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[Destinatario]( [GUID_destinatario] [identificatore univoco] ROWGUIDCOL NOT NULL, [Nome_destinatario] [nvarchar](255) NOT NULL, // un'e-mail principale del destinatario [ Recipient_Code] [nvarchar](10) NOT NULL, // il codice del destinatario [IsDeleted] [bit] NOT NULL, // un indicatore di eliminazione (se un destinatario è utilizzato o meno) [InsertUTCDate] [datetime] NOT NULL, CONSTRAINT [PK_Recipient ] CHIAVE PRIMARIA CLUSTERED ( [GUID_destinatario] ASC)CON (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY], CONSTRAINT [AK_Recipient_Code] UNICO NON CLUSTERED ( [Codice_destinatario] ASC)CON (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY], CONSTRAINT [AK_Nome_destinatario] UNICO NON CLUSTERED ([Nome_destinatario] ASC)CON (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OF F, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY]TABELLA DEL GOALTER [srv].[Destinatario] AGGIUNGI VINCOLI [GUID_destinatario_destinatario_DF] PREDEFINITO (newssequentialid()) PER [GUID_destinatario]TABELLA DEL GOALTER [ srv].[Destinatario] ADD CONSTRAINT [DF_Recipient_IsDeleted] DEFAULT ((0)) PER [IsDeleted]GOALTER TABLE [srv].[Destinatario] ADD CONSTRAINT [DF_Recipient_InsertUTCDate] DEFAULT (getutcdate()) PER [InsertUTCDate]GO
[/expand]
3. Crea una tabella per gli indirizzi dei destinatari:
[expand title =”Codice”]
USE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[Address]( [Address_GUID] [uniqueidentifier] ROWGUIDCOL NOT NULL, [Recipient_GUID] [uniqueidentifier] NOT NULL, // destinatario [Address] [nvarchar]( 255) NOT NULL, // email [IsDeleted] [bit] NOT NULL, // indicatore di eliminazione (se l'email è utilizzata o meno) [InsertUTCDate] [datetime] NOT NULL, CONSTRAINT [PK_Address] PRIMARY KEY CLUSTERED ( [Address_GUID] ASC )CON (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY], CONSTRAINT [AK_Address] UNIQUE NON CLUSTERED ( [Recipient_GUID] ASC, [Address] ASC)CON (PAD_INDEX =OFF , STATISTICS_NORECOMPUTE =OFF, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY]GOALTER TABLE [srv].[Address] ADD CONSTRAINT [DF_Address_Address_GUID] DEFAULT (newssequentialid()) PER [Address_GUID] TABELLA DEI PORTIERI [ srv].[Address] ADD CONSTRAINT [DF_Address_IsDeleted] DEFAULT ((0)) PER [IsDeleted]GOALTER TABLE [srv].[Address] ADD CONSTRAINT [DF_Address_InsertUTCDate] DEFAULT (getutcdate()) PER [InsertUTCDate]GO
[/expand]
4. Crea una tabella per una coda di messaggi:
[expand title =”Codice”]
USE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[ErrorInfo]( [ErrorInfo_GUID] [uniqueidentifier] NOT NULL, [ERROR_TITLE] [nvarchar](max) NULL, // title [ERROR_PRED_MESSAGE] [nvarchar] (max) NULL, // informazioni preliminari [ERROR_NUMBER] [nvarchar](max) NULL, // codice messaggio (errore) [ERROR_MESSAGE] [nvarchar](max) NULL, // messaggio [ERROR_LINE] [nvarchar](max) NULL, // numero di riga [ERROR_PROCEDURE] [nvarchar](max) NULL, // stored procedure [ERROR_POST_MESSAGE] [nvarchar](max) NULL, // informazioni esplicative [RECIPIENTS] [nvarchar](max) NULL, // destinatari separati da ';' [InsertDate] [datetime] NOT NULL, [StartDate] [datetime] NOT NULL, // data e ora di inizio [FinishDate] [datetime] NOT NULL, // data e ora di fine [Count] [int] NOT NULL, // numero di volte [UpdateDate] [dat etime] NOT NULL, [IsRealTime] [bit] NOT NULL, // indicatore in tempo reale [InsertUTCDate] [datetime] NULL, CONSTRAINT [PK_ErrorInfo] PRIMARY KEY CLUSTERED ( [ErrorInfo_GUID] ASC)WITH (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]GOALTER TABLE [srv].[ErrorInfo] AGGIUNGI CONSTRAINT [DF_ErrorInfo_ErrorInfo_GUID] PREDEFINITO (newid()) PER [ErrorInfo_GUID]GOALTER TABLE [srv].[ErrorInfo] ADD CONSTRAINT [DF_ErrorInfo_InsertDate] PREDEFINITO (getdate()) PER [InsertDate]GOALTER TABLE [srv].[ErrorInfo] ADD CONSTRAINT [DF_ErrorInfo_StartDate] DEFAULT (getdate()) PER [StartDate]GOALTER TABLE [ srv].[ErrorInfo] ADD CONSTRAINT [DF_ErrorInfo_FinishDate] DEFAULT (getdate()) PER [FinishDate]GOALTER TABLE [srv].[ErrorInfo] ADD CONSTRAINT [DF_ErrorInfo_Count] DEFAULT ((1)) PER [Count]GOALTER TABLE [srv] .[ErrorInfo] AGGIUNGI VINCOLO [DF__ErrorInfo__Updat__5FFEE747] DEFAU LT (getdate()) PER [UpdateDate]TABELLA DEL GOALTER [srv].[ErrorInfo] AGGIUNGI VINCOLO [DF_ErrorInfo_IsRealTime] PREDEFINITO ((0)) PER [IsRealTime]TABELLA DEL GOALTER [srv].[ErrorInfo] AGGIUNGI VINCOLO [DF_ErrorInfo_InsertUTCDate] PREDEFINITO ( getutcdate()) PER [InsertUTCDate]GO
[/expand]
5. Crea una tabella di archivio per i messaggi inviati dalla coda dei messaggi:
[expand title =”Codice”]
USE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[ErrorInfoArchive]( [ErrorInfo_GUID] [uniqueidentifier] ROWGUIDCOL NOT NULL, [ERROR_TITLE] [nvarchar](max) NULL, [ERROR_PRED_MESSAGE] [nvarchar](max ) NULL, [ERROR_NUMBER] [nvarchar](max) NULL, [ERROR_MESSAGE] [nvarchar](max) NULL, [ERROR_LINE] [nvarchar](max) NULL, [ERROR_PROCEDURE] [nvarchar](max) NULL, [ERROR_POST_MESSAGE] [nvarchar](max) NULL, [RECIPIENTS] [nvarchar](max) NULL, [InsertDate] [datetime] NOT NULL, [StartDate] [datetime] NOT NULL, [FinishDate] [datetime] NOT NULL, [Count] [ int] NOT NULL, [UpdateDate] [datetime] NOT NULL, [IsRealTime] [bit] NOT NULL, [InsertUTCDate] [datetime] NULL, CONSTRAINT [PK_ArchiveErrorInfo] CHIAVE PRIMARIA CLUSTERED ( [ErrorInfo_GUID] ASC)CON (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]GOALTE R TABLE [srv].[ErrorInfoArchive] ADD CONSTRAINT [DF_ErrorInfoArchive_ErrorInfo_GUID] DEFAULT (newssequentialid()) PER [ErrorInfo_GUID]GOALTER TABLE [srv].[ErrorInfoArchive] ADD CONSTRAINT [DF_ArchiveErrorInfo_InsertDate] DEFAULT (getdate()) PER [InsertDate]GOALTER TABLE [srv].[ErrorInfoArchive] AGGIUNGI CONSTRAINT [DF_ErrorInfoArchive_StartDate] PREDEFINITO (getdate()) PER [StartDate]TABELLA DEL GOALTER [srv].[ErrorArchive] ADD CONSTRAINT [DF_ErrorInfoArchive_FinishDate] PREDEFINITO (getdate()) PER [FinishDate]TABELLA DEL GOALTER [srv ].[ErrorInfoArchive] AGGIUNGI CONSTRAINT [DF_ErrorInfoArchive_Count] PREDEFINITO ((1)) PER [Conteggio]TABELLA DEL GOALTER [srv].[ErrorInfoArchive] AGGIUNGI CONSTRAINT [DF_ErrorInfoArchive_Update] PREDEFINITO (getdate()) PER [UpdateDate]TABELLA DEL GOALTER [srv]. [ErrorInfoArchive] ADD CONSTRAINT [DF_ErrorInfoArchive_IsRealTime] DEFAULT ((0)) PER [IsRealTime]GOALTER TABLE [srv].[ErrorInfoArchive] ADD CONSTRAINT [DF_ErrorInfoArchive_InsertUTCDate] DEFAULT (getutcdate()) PER [InsertUTCDate]GO[/expand]
Queste informazioni sono necessarie per la cronologia. Inoltre, questa tabella deve essere cancellata da dati molto vecchi (ad esempio, più vecchi di un mese).
6. Crea una procedura memorizzata che registra un nuovo messaggio nella coda dei messaggi:
[expand title =”Codice”]
USE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [srv].[ErrorInfoIncUpd] @ERROR_TITLE nvarchar(max), @ERROR_PRED_MESSAGE nvarchar(max), @ERROR_NUMBER nvarchar(max), @ERROR_MESSAGE nvarchar(max), @ERROR_LINE nvarchar(max), @ERROR_PROCEDURE nvarchar(max), @ERROR_POST_MESSAGE nvarchar(max), @RECIPIENTS nvarchar(max), @StartDate datetime=null, @FinishDate datetime=null, @IsRealTime bit =0ASBEGIN /* Errore durante la registrazione dell'errore tabella da inviare via email se la tabella ha già una voce con lo stesso titolo, contenuto e mittente, la data di fine dell'errore, la data di aggiornamento del record, nonché il numero di errori cambieranno */ SET NOCOUNT SU; dichiarare @ErrorInfo_GUID identificatore univoco; seleziona top 1 @ErrorInfo_GUID=ErrorInfo_GUID da srv.ErrorInfo dove ([email protected]_TITLE o @ERROR_TITLE è nullo) e [email protected] e ([email protected]_MESSAGE o @ERROR_MESSAGE è null) e ([email protected]_PRED_MESSAGE o @ERROR_PRED_MESSAGE è null) e ([email protected]_POST_MESSAGE o @ERROR_POST_MESSAGE è null) e ([email protected] o @IsRealTime è null); if(@ErrorInfo_GUID is null) inizia a inserire in srv.ErrorInfo ( ERROR_TITLE ,ERROR_PRED_MESSAGE ,ERROR_NUMBER ,ERROR_MESSAGE ,ERROR_MESSAGE ,ERROR_LINE ,ERROR_PROCEDURE ,ERROR_POST_MESSAGE ,RECIPIENTS ,IsRealTime ,StartDate ,FinishDate ) select @ERROR_TITLE ,@ERROR_PRED_MESSAGE ,@ERRORMESS_NUMBER ERROR_LINE ,@ERROR_PROCEDURE ,@ERROR_POST_MESSAGE ,@RECIPIENTS ,@IsRealTime ,isnull(@StartDate, getdate()) ,isnull(@FinishDate,getdate()) fine altrimenti inizia l'aggiornamento srv.ErrorInfo set FinishDate=getdate(), [Count]=[Count]+1, UpdateDate=getdate() where [email protected]_GUID; endENDGO[/expand]
7. Crea una stored procedure che restituisca una stringa dagli indirizzi tramite il codice o l'indirizzo email principale di un destinatario:
[expand title =”Codice”]
USE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [srv].[GetRecipients]@Nome_destinatario nvarchar(255)=NULL,@Codice_destinatario nvarchar(10)=NULL,@destinatario nvarchar(max) out/* La procedura per creazione di notifiche e-mail*/ASBEGIN SET NOCOUNT ON; imposta @Destinatari=''; seleziona @[email protected]+d.[Indirizzo]+';' from srv.Recipient as r inner join srv.[Address] as d on r.Recipient_GUID=d.Recipient_GUID dove ([email protected]_Name or @Recipient_Name IS NULL) e ([email protected]_Code or @Recipient_Code IS NULL) e r.IsDeleted=0 e d.IsDeleted=0; --order by r.InsertUTCDate desc, d.InsertUTCDate desc; if(len(@Destinatari)>0) set @Destinatari=substring(@Destinatari,1,len(@Destinatari)-1);ENDGO[/expand]
8. Crea le funzioni necessarie per lavorare con date e ora:
[expand title =”Codice”]
USE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE FUNCTION [rep].[GetDateFormat] ( @dt datetime, // input date @format int=0 // preset format)RETURNS nvarchar(255)AS/* Restituisce la data come una stringa secondo il formato specificato e la data di input Inserisce degli zeri ove necessario:format data di input risultato 0 17.4.2014 "17.04.2014" 1 17.4.2014 "04.2014" 1 8.11.2014 "11.2014" 2 17.04.2014 "2014" */INIZIA A DICHIARARE @res nvarchar(255); DICHIARA @giorno int=GIORNO(@dt); DICHIARA @mese int=MESE(@dt); DICHIARA @anno int=ANNO(@dt); if(@format=0) begin set @res=IIF(@day<10,'0'+cast(@day as nvarchar(1)), cast(@day as nvarchar(2)))+'.'; set @[email protected]+IIF(@mese<10,'0'+cast(@mese come nvarchar(1)), cast(@mese come nvarchar(2)))+'.'; set @[email protected]+cast(@year as nvarchar(255)); end else if(@format=1) begin set @res=IIF(@mese<10,'0'+cast(@mese come nvarchar(1)), cast(@mese come nvarchar(2)))+'. '; set @[email protected]+cast(@year as nvarchar(255)); end else if(@format=2) begin set @res=cast(@year as nvarchar(255)); end RETURN @res;ENDGOUSE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE FUNCTION [rep].[GetTimeFormat] ( @dt datetime, // input time @format int=0 // preset format)RETURNS nvarchar(255)AS/* Returns ora come stringa secondo il formato specificato e l'ora di input Inserisce zeri dove necessario:format input time result 0 17:04 "17:04:00" 1 17:04 "17:04" 1 8:04 "08:04 " 2 17:04 "17"*/INIZIA A DICHIARARE @res nvarchar(255); DICHIARA @hour int=DATEPART(HOUR, @dt); DICHIARA @min int=DATEPART(MINUTE, @dt); DICHIARA @sec int=DATAPART(SECONDA, @dt); if(@format=0) begin set @res=IIF(@hour<10,'0'+cast(@hour as nvarchar(1)), cast(@hour as nvarchar(2)))+':'; set @[email protected]+IIF(@min<10,'0'+cast(@min as nvarchar(1)), cast(@min as nvarchar(2)))+':'; set @[email protected]+IIF(@sec<10,'0'+cast(@sec come nvarchar(1)), cast(@sec come nvarchar(2))); end else if(@format=1) begin set @res=IIF(@hour<10,'0'+cast(@hour as nvarchar(1)), cast(@hour as nvarchar(2)))+':'; set @[email protected]+IIF(@min<10,'0'+cast(@min come nvarchar(1)), cast(@min come nvarchar(2))); end else if(@format=2) begin set @res=IIF(@hour<10,'0'+cast(@hour as nvarchar(1)), cast(@hour as nvarchar(2))); end RETURN @res;ENDGO[/expand]
9. Crea una procedura memorizzata che crea un report HTML sui messaggi sotto forma di tabella:
[expand title =”Codice”]
USE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [srv].[GetHTMLTable] @recipients nvarchar(max) ,@dt datetime // entro quale data leggereASBEGIN /* genera codice HTML per la tabella */ SET NOCOUNT ON; dichiarare @body nvarchar(max); dichiara @tbl table(ID int identity(1,1) ,[ERROR_TITLE] nvarchar(max) ,[ERROR_PRED_MESSAGE] nvarchar(max) ,[ERROR_NUMBER] nvarchar(max) ,[ERROR_MESSAGE] nvarchar(max) ,[ERROR_LINE] nvarchar (max) ,[ERROR_PROCEDURE] nvarchar(max) ,[ERROR_POST_MESSAGE] nvarchar(max) ,[InsertDate] datetime ,[StartDate] datetime ,[FinishDate] datetime ,[Count] int ); dichiara @ID int ,@ERROR_TITLE nvarchar(max) ,@ERROR_PRED_MESSAGE nvarchar(max) ,@ERROR_NUMBER nvarchar(max) ,@ERROR_MESSAGE nvarchar(max) ,@ERROR_LINE nvarchar(max) ,@ERROR_PROCEDURE nvarchar(max) ,@ERROR_POST_MESSAGE nvarchar (max) ,@InsertDate datetime ,@StartDate datetime ,@FinishDate datetime ,@Count int insert in @tbl( [ERROR_TITLE] ,[ERROR_PRED_MESSAGE] ,[ERROR_NUMBER] ,[ERROR_MESSAGE] ,[ERROR_LINE] ,[ERROR_PROCEDURE] ,[ERROR_POST_MESSAGE ] ,[InsertDate] ,[StartDate] ,[FinishDate] ,[Count] ) seleziona i primi 100 [ERROR_TITLE] ,[ERROR_PRED_MESSAGE] ,[ERROR_NUMBER] ,[ERROR_MESSAGE] ,[ERROR_LINE] ,[ERROR_PROCEDURE] ,[ERROR_POST_MESSAGE] ,[InsertDate] ,[StartDate] ,[FinishDate] ,[Count] from [srv].[ErrorInfo] dove ([RECIPIENTS][email protected] ) o (@recipients IS NULL) e InsertDate'; set @example@sqldat.com+' '; set @[email protected]+' '; while((seleziona i primi 1 1 da @tbl)>0) inizia set @[email protected]+''; imposta @[email protected]+'№ п/п'; imposta @[email protected]+' '; set @[email protected]+''; imposta @[email protected]+'DATE'; imposta @[email protected]+' '; set @[email protected]+''; imposta @[email protected]+'ERRORE'; imposta @[email protected]+' '; set @[email protected]+''; set @[email protected]+'DESCRIZIONE'; imposta @[email protected]+' '; set @[email protected]+''; set @[email protected]+'CODICE DI ERRORE'; imposta @[email protected]+' '; set @[email protected]+''; imposta @[email protected]+'MESSAGGIO'; imposta @[email protected]+' '; set @[email protected]+''; imposta @[email protected]+'START'; imposta @[email protected]+' '; set @[email protected]+''; imposta @[email protected]+'FINISH'; imposta @[email protected]+' '; set @[email protected]+''; imposta @[email protected]+'NUMERO'; imposta @[email protected]+' '; set @[email protected]+''; imposta @[email protected]+'NUMERO DI RIGA'; imposta @[email protected]+' '; set @[email protected]+''; imposta @[email protected]+'PROCEDURA'; imposta @[email protected]+' '; set @[email protected]+''; imposta @[email protected]+'NOTA'; imposta @[email protected]+' '; imposta @[email protected]+''; seleziona i primi 1 @ID =[ID] ,@ERROR_TITLE =[ERROR_TITLE] ,@ERROR_PRED_MESSAGE=[ERROR_PRED_MESSAGE] ,@ERROR_NUMBER =[ERROR_NUMBER] ,@ERROR_MESSAGE =[ERROR_MESSAGE] ,@ERROR_LINE =[ERROR_LINE] ,@ERROR_PROCEDURE =[ERROR_PROCEDURE ] ,@ERROR_POST_MESSAGE=[ERROR_POST_MESSAGE] ,@InsertDate =[InsertDate] ,@StartDate =[StartDate] ,@FinishDate =[FinishDate] ,@Count =[Count] from @tbl order by InsertDate asc; set @[email protected]+' '; end set @[email protected]+''; seleziona @body;ENDGO'; imposta @[email protected]+cast(@ID come nvarchar(max)); imposta @[email protected]+' '; set @[email protected]+''; set @[email protected]+rep.GetDateFormat(@InsertDate, default)+' '+rep.GetTimeFormat(@InsertDate, default); // cast(@InsertDate as nvarchar(max)); imposta @[email protected]+' '; set @[email protected]+''; set @[email protected]+isnull(@ERROR_TITLE,''); imposta @[email protected]+' '; set @[email protected]+''; set @[email protected]+isnull(@ERROR_PRED_MESSAGE,''); imposta @[email protected]+' '; set @[email protected]+''; set @[email protected]+isnull(@ERROR_NUMBER,''); imposta @[email protected]+' '; set @[email protected]+''; set @[email protected]+isnull(@ERROR_MESSAGE,''); imposta @[email protected]+' '; set @[email protected]+''; set @[email protected]+rep.GetDateFormat(@StartDate, predefinito)+' '+rep.GetTimeFormat(@StartDate, predefinito); //cast(@StartDate as nvarchar(max)); imposta @[email protected]+' '; set @[email protected]+''; set @[email protected]+rep.GetDateFormat(@FinishDate, predefinito)+' '+rep.GetTimeFormat(@FinishDate, predefinito); //cast(@FinishDate as nvarchar(max)); imposta @[email protected]+' '; set @[email protected]+''; set @[email protected]+cast(@Count as nvarchar(max)); imposta @[email protected]+' '; set @[email protected]+''; set @[email protected]+isnull(@ERROR_LINE,''); imposta @[email protected]+' '; set @[email protected]+''; set @[email protected]+isnull(@ERROR_PROCEDURE,''); imposta @[email protected]+' '; set @[email protected]+''; set @[email protected]+isnull(@ERROR_POST_MESSAGE,''); imposta @[email protected]+' '; elimina da @tbl dove [email protected]; imposta @[email protected]+'[/expand]
10. Crea una procedura memorizzata che invii messaggi:
[expand title =”Codice”]
USE [DATABAE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [srv].[RunErrorInfoProc] @IsRealTime bit =0 // modalità di invio (1-tempo reale)ASBEGIN /* invio di notifiche di errore con la modalità specificata */ SET NOCOUNT ON; dichiara @dt datetime=getdate(); dichiarare @tbl table(Destinatari nvarchar(max)); dichiara @recipients nvarchar(max); dichiara @recipient nvarchar(255); dichiara @result nvarchar(max)=''; dichiara @recp nvarchar(max); dichiara @ind int; dichiarare @recipients_key nvarchar(max); // ricevi tutti i messaggi necessari inserisci in @tbl(Destinatari) seleziona [DESTINATARI] da srv.ErrorInfo dove InserisciDate0) inizia //ricevi i destinatari seleziona i primi (1) @recipients=Destinatari da @tbl; imposta @[email protected]; imposta @risultato=''; // per ogni destinatario while(len(@recipients)>0) begin set @ind=CHARINDEX(';', @recipients); if(@ind>0) begin set @recipient=substring(@recipients,1, @ind-1); set @recipients=substring(@recipients,@ind+1,len(@recipients)[email protected]); fine altrimenti inizia set @[email protected]; imposta @destinatario=''; fine; // ricevere le email dei destinatari exec [srv].[GetRecipients] @[email protected], @[email protected] out; if(len(@recp)=0) inizia exec [srv].[GetRecipients] @[email protected], @[email protected] out; if(len(@recp)=0) set @[email protected]; fine // separato dal simbolo ';' set @[email protected]@sqldat.com+';'; end set @result=substring(@result,1,len(@result)-1); imposta @[email protected]; // riceve il report HTML con i destinatari specificati e la data inserita in @rec_body(Body) exec srv.GetHTMLTable @[email protected]_key, @[email protected]; // ricevi report HTML seleziona top (1) @body=Body da @rec_body; // l'effettivo EXEC di invio msdb.dbo.sp_send_dbmail // il profilo dell'amministratore dell'e-mail che abbiamo creato @profile_name ='ALARM', //e-mail del destinatario @recipients =@recipients, // testo di un messaggio @body =@body, // Oggetto @subject =N'INFORMATION ON EXECUTION ERRORS', @body_format='HTML'--, // Ad esempio, aggiungiamo i risultati di una query SQL casuale al messaggio [email protected] =@query--'SELECT TOP 10 nome DA sys.objects'; elimina da @tbl dove [email protected]_key; elimina da @rec_body; end // archivia i messaggi inviati INSERT INTO [srv].[ErrorInfoArchive] ([ErrorInfo_GUID] ,[ERROR_TITLE] ,[ERROR_PRED_MESSAGE] ,[ERROR_NUMBER] ,[ERROR_MESSAGE] ,[ERROR_LINE] ,[ERROR_PROCEDURE] ,[ERROR_POST_MESSAGE] ,[ DESTINATARI] ,[StartDate] ,[FinishDate] ,[Count] ,IsRealTime ) SELECT [ErrorInfo_GUID] ,[ERROR_TITLE] ,[ERROR_PRED_MESSAGE] ,[ERROR_NUMBER] ,[ERROR_MESSAGE] ,[ERROR_LINE] ,[ERROR_PROCEDURE] ,[ERROR_POST_MESSAGE] , [DESTINATARI] ,[StartDate] ,[FinishDate] ,[Count] ,IsRealTime FROM [srv].[ErrorInfo] dove [email protected] e InsertDate [/expand]
Questa procedura memorizzata prende ogni messaggio dalla coda dei messaggi e lo racchiude in un report HTML sotto forma di tabella. Per i destinatari, in base al loro codice o indirizzo email principale, crea una stringa composta da indirizzi email, a cui viene inviato un messaggio. In questo modo vengono elaborati tutti i messaggi selezionati. Qui viene utilizzata la procedura memorizzata msdb.dbo.sp_send_dbmail.
11. Crea due attività in Agent (la prima è per le notifiche in tempo reale (programma 1 volta al minuto), la seconda è per le notifiche semplici (programma 1 volta all'ora)). Aggiungi quanto segue al codice dell'attività:
ESEGUI [NOME_DATABASE].[srv].[RunErrorInfoProc] @IsRealTime=0; // 0 - per messaggi semplici e 1 - per messaggi in tempo realeEcco un esempio di segnalazione degli errori:
[expand title="Codice"]
comincia a provare exec [DATABASE_NAME].[srv].[KillFullOldConnect];end trybegin catch dichiarare @str_mess nvarchar(max)=ERROR_MESSAGE(), @str_num nvarchar(max)=cast(ERROR_NUMBER() as nvarchar(max) ), @str_line nvarchar(max)=cast(ERROR_LINE() as nvarchar(max)), @str_proc nvarchar(max)=ERROR_PROCEDURE(), @str_title nvarchar(max)='ELIMINAZIONE DEI PROCESSI CHE NON RISPONDONO SUL SERVER 'example @sqldat.com@nomeserver, @str_pred_mess nvarchar(max)='LA CANCELLAZIONE DELL'ERRORE DI PROCESSO CHE NON RISPONDE SI È VERIFICATA SUL SERVER '[email protected]@servername+'; exec [DATABASE_NAME].srv.ErrorInfoIncUpd @ERROR_TITLE =@str_title, @ERROR_PRED_MESSAGE =@str_pred_mess, @ERROR_NUMBER =@str_num, @ERROR_MESSAGE =@str_mess, @ERROR_LINE =@str_line, @ERROR_PROCEDURE =@str_proc, @ERROR_POST_MESSAGE =NULL, @ DESTINATARI ='DESTINATARIO1;DESTINATARIO2'; dichiara @err [email protected]@errore; raiserror(@str_mess,16,1);fine cattura[/expand]
Qui viene utilizzata la procedura memorizzata svr.KillFullOldConnect.
Risultato
Questo articolo include un esempio di estensione della funzionalità di una normale posta elettronica database e un esempio di come generare notifiche nelle tabelle HTML e quindi inviarle tramite posta elettronica agli amministratori. Questo approccio consente di notificare agli amministratori diversi problemi in tempo reale o dopo un certo tempo, riducendo così al minimo il verificarsi di un problema critico e il guasto di DBMS e server, che a sua volta protegge la produzione dal ritardo del flusso di lavoro.
Riferimenti:
- Sp_send_dbmail
- Posta database
- Srv.KillFullOldConnect