Einführung
Oft besteht die Notwendigkeit, Administratoren irgendwie über die Probleme mit einem Server zu informieren. Benachrichtigungen werden im Allgemeinen in 2 Typen unterteilt:
1) Echtzeitbenachrichtigungen, also solche, die sofort kommen müssen, wenn ein Problem auftritt
2) verzögerte Benachrichtigungen, d. h. solche, die nach einer ziemlich langen Zeit (mehr als 1 Stunde) nach dem Auftreten eines Problems eintreffen.
In meiner Arbeit war es notwendig, die Funktionalität der regulären SQL Server-Datenbank-E-Mail zu erweitern.
In diesem Artikel betrachten wir ein Beispiel dafür, wie Benachrichtigungen in HTML-Tabellen generiert und dann an Administratoren gesendet werden.
Lösung
1. Datenbank-E-Mail konfigurieren
2. Erstellen Sie eine Tabelle für Empfänger:
[expand title =”Code”]
USE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[Recipient]( [Recipient_GUID] [uniqueidentifier] ROWGUIDCOL NOT NULL, [Recipient_Name] [nvarchar](255) NOT NULL, // eine primäre E-Mail-Adresse des Empfängers [ Recipient_Code] [nvarchar](10) NOT NULL, // Code des Empfängers [IsDeleted] [bit] NOT NULL, // ein Löschindikator (ob ein Empfänger verwendet wird oder nicht) [InsertUTCDate] [datetime] NOT NULL, CONSTRAINT [PK_Recipient ] PRIMARY KEY CLUSTERED ([Recipient_GUID] ASC)WITH (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY], CONSTRAINT [AK_Recipient_Code] UNIQUE NONCLUSTERED ([Recipient_Code] ASC)WITH (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY], CONSTRAINT [AK_Recipient_Name] UNIQUE NONCLUSTERED ([Recipient_Name] ASC)WITH (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OF F, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY]GOALTER TABLE [srv].[Empfänger] ADD CONSTRAINT [DF_Recipient_Recipient_GUID] DEFAULT (newsequentialid()) FOR [Recipient_GUID]GOALTER TABLE [ srv].[Empfänger] ADD CONSTRAINT [DF_Recipient_IsDeleted] DEFAULT ((0)) FOR [IsDeleted]GOALTER TABLE [srv].[Empfänger] ADD CONSTRAINT [DF_Recipient_InsertUTCDate] DEFAULT (getutcdate()) FOR [InsertUTCDate]GO
[/expand]
3. Erstellen Sie eine Tabelle für die Adressen der Empfänger:
[expand title =”Code”]
USE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[Adresse]( [Adresse_GUID] [eindeutiger Bezeichner] ROWGUIDCOL NOT NULL, [Empfänger_GUID] [eindeutiger Bezeichner] NOT NULL, // Empfänger [Adresse] [nvarchar]( 255) NOT NULL, // E-Mail [IsDeleted] [bit] NOT NULL, // Löschindikator (ob E-Mail verwendet wird oder nicht) [InsertUTCDate] [datetime] NOT NULL, CONSTRAINT [PK_Address] PRIMARY KEY CLUSTERED ( [Address_GUID] ASC )WITH (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY], CONSTRAINT [AK_Address] UNIQUE NONCLUSTERED ([Recipient_GUID] ASC, [Address] ASC)WITH (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].[Adresse] ADD CONSTRAINT [DF_Address_Address_GUID] DEFAULT (newsequentialid()) FOR [Address_GUID] TORTABELLE [ srv].[Adresse] ADD CONSTRAINT [DF_Address_IsDeleted] DEFAULT ((0)) FOR [IsDeleted]GOALTER TABLE [srv].[Adresse] ADD CONSTRAINT [DF_Address_InsertUTCDate] DEFAULT (getutcdate()) FOR [InsertUTCDate]GO
[/expand]
4. Erstellen Sie eine Tabelle für eine Nachrichtenwarteschlange:
[expand title =”Code”]
USE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[ErrorInfo]( [ErrorInfo_GUID] [uniqueidentifier] NOT NULL, [ERROR_TITLE] [nvarchar](max) NULL, // Titel [ERROR_PRED_MESSAGE] [nvarchar] (max) NULL, // vorläufige Informationen [ERROR_NUMBER] [nvarchar](max) NULL, // Meldung (Fehler) Code [ERROR_MESSAGE] [nvarchar](max) NULL, // Meldung [ERROR_LINE] [nvarchar](max) NULL, // Zeilennummer [ERROR_PROCEDURE] [nvarchar](max) NULL, // gespeicherte Prozedur [ERROR_POST_MESSAGE] [nvarchar](max) NULL, // erläuternde Informationen [RECIPIENTS] [nvarchar](max) NULL, // Empfänger getrennt durch ';' [Einfügedatum] [DatumUhrzeit] NICHT NULL, [Startdatum] [DatumUhrzeit] NICHT NULL, // Startdatum und -uhrzeit [Enddatum] [DatumUhrzeit] NOT NULL, // Enddatum und -Uhrzeit [Anzahl] [int] NOT NULL, // wie oft [UpdateDate] [dat etime] NOT NULL, [IsRealTime] [bit] NOT NULL, // Echtzeitindikator [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] ADD CONSTRAINT [DF_ErrorInfo_ErrorInfo_GUID] DEFAULT (newid()) FOR [ErrorInfo_GUID]GOALTER TABLE [srv].[ErrorInfo] ADD CONSTRAINT [DF_ErrorInfo_InsertDate] DEFAULT (getdate()) FOR [InsertDate]GOALTER TABLE [srv].[ErrorInfo] ADD CONSTRAINT [DF_ErrorInfo_StartDate] DEFAULT (getdate()) FOR [StartDate]GOALTER TABLE [ srv].[ErrorInfo] ADD CONSTRAINT [DF_ErrorInfo_FinishDate] DEFAULT (getdate()) FOR [FinishDate]TORTABELLE [srv].[ErrorInfo] ADD CONSTRAINT [DF_ErrorInfo_Count] DEFAULT ((1)) FOR [Count]TORTABELLE [srv] .[ErrorInfo] EINSCHRÄNKUNG HINZUFÜGEN [DF__ErrorInfo__Update__5FFEE747] DEFAU LT (getdate()) FOR [UpdateDate]GOALTER TABLE [srv].[ErrorInfo] ADD CONSTRAINT [DF_ErrorInfo_IsRealTime] DEFAULT ((0)) FOR [IsRealTime]GOALTER TABLE [srv].[ErrorInfo] ADD CONSTRAINT [DF_ErrorInfo_InsertUTCDate] DEFAULT ( getutcdate()) FOR [InsertUTCDate]GO
[/expand]
5. Erstellen Sie eine Archivtabelle für Nachrichten, die aus der Nachrichtenwarteschlange gesendet werden:
[expand title =”Code”]
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] 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]GOALTE R TABLE [srv].[ErrorInfoArchive] ADD CONSTRAINT [DF_ErrorInfoArchive_ErrorInfo_GUID] DEFAULT (newsequentialid()) FOR [ErrorInfo_GUID]TORTABELLE [srv].[ErrorInfoArchive] ADD CONSTRAINT [DF_ArchiveErrorInfo_InsertDate] STANDARD (getdate()) FOR [InsertDate]TORTABELLE [srv].[ErrorInfoArchive] ADD CONSTRAINT [DF_ErrorInfoArchive_StartDate] DEFAULT (getdate()) FOR [StartDate]TORTABELLE [srv].[ErrorInfoArchive] ADD CONSTRAINT [DF_ErrorInfoArchive_FinishDate] DEFAULT (getdate()) FOR [FinishDate]TORTABELLE [srv ].[ErrorInfoArchive] ADD CONSTRAINT [DF_ErrorInfoArchive_Count] DEFAULT ((1)) FOR [Count]GOALTER TABLE [srv].[ErrorInfoArchive] ADD CONSTRAINT [DF_ErrorInfoArchive_UpdateDate] DEFAULT (getdate()) FOR [UpdateDate]GOALTER TABLE [srv]. [ErrorInfoArchive] ADD CONSTRAINT [DF_ErrorInfoArchive_IsRealTime] DEFAULT ((0)) FOR [IsRealTime]TORTABELLE [srv].[ErrorInfoArchive] ADD CONSTRAINT [DF_ErrorInfoArchive_InsertUTCDate] DEFAULT (getutcdate()) FOR [InsertUTCDate]GO[/expand]
Diese Information wird für die Historie benötigt. Außerdem muss diese Tabelle von sehr alten Daten (z. B. älter als einen Monat) bereinigt werden.
6. Erstellen Sie eine gespeicherte Prozedur, die eine neue Nachricht in der Nachrichtenwarteschlange registriert:
[expand title =”Code”]
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 /* Fehlerprotokollierung des Fehlers per E-Mail zu versendende Tabelle Wenn die Tabelle bereits einen Eintrag mit gleichem Titel, Inhalt und Absender enthält, ändern sich das Enddatum des Fehlers, das Datum der Datensatzaktualisierung sowie die Anzahl der Fehler */ SET NOCOUNT AN; deklarieren Sie @ErrorInfo_GUID uniqueidentifier; select top 1 @ErrorInfo_GUID=ErrorInfo_GUID from srv.ErrorInfo where (example@sqldat.com_TITLE or @ERROR_TITLE is null) and example@sqldat.com and (example@sqldat.com_MESSAGE or @ERROR_MESSAGE is null) and (example@sqldat.com_PRED_MESSAGE oder @ERROR_PRED_MESSAGE ist null) und (example@sqldat.com_POST_MESSAGE oder @ERROR_POST_MESSAGE ist null) und (example@sqldat.com oder @IsRealTime ist null); if(@ErrorInfo_GUID is null) begin insert into srv.ErrorInfo ( ERROR_TITLE ,ERROR_PRED_MESSAGE ,ERROR_NUMBER ,ERROR_MESSAGE ,ERROR_LINE ,ERROR_PROCEDURE ,ERROR_POST_MESSAGE ,RECIPIENTS ,IsRealTime ,StartDate ,FinishDate ) select @ERROR_TITLE ,@ERROR_PRED_MESSAGE ,@ERROR_NUMBER ,@ERROR_MESSAGE ,@ ERROR_LINE ,@ERROR_PROCEDURE ,@ERROR_POST_MESSAGE ,@RECIPIENTS ,@IsRealTime ,isnull(@StartDate, getdate()) ,isnull(@FinishDate,getdate()) end else begin update srv.ErrorInfo set FinishDate=getdate(), [Count]=[Count]+1, UpdateDate=getdate() where example@sqldat.com_GUID; endENDGO[/expand]
7. Erstellen Sie eine gespeicherte Prozedur, die eine Zeichenfolge aus den Adressen nach dem Code oder der primären E-Mail-Adresse eines Empfängers zurückgibt:
[expand title =”Code”]
USE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [srv].[GetRecipients]@Recipient_Name nvarchar(255)=NULL,@Recipient_Code nvarchar(10)=NULL,@Recipients nvarchar(max) out/* Das Verfahren für Erstellen von E-Mail-Benachrichtigungen*/ASBEGIN SET NOCOUNT ON; setze @Empfänger=''; select @example@sqldat.com+d.[Adresse]+';' from srv.Recipient as r inner join srv.[Address] as d on r.Recipient_GUID=d.Recipient_GUID wobei (example@sqldat.com_Name or @Recipient_Name IS NULL) and (example@sqldat.com_Code or @Recipient_Code IS NULL) and r.IsDeleted=0 und d.IsDeleted=0; --order by r.InsertUTCDate desc, d.InsertUTCDate desc; if(len(@Recipients)>0) set @Recipients=substring(@Recipients,1,len(@Recipients)-1);ENDGO[/expand]
8. Erstellen Sie die notwendigen Funktionen für die Arbeit mit Datum und Uhrzeit:
[expand title =”Code”]
USE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE FUNCTION [rep].[GetDateFormat] ( @dt datetime, // Eingabedatum @format int=0 // voreingestelltes Format)RETURNS nvarchar(255)AS/* Gibt das Datum zurück als eine Zeichenfolge gemäß dem angegebenen Format und dem eingegebenen Datum Fügt bei Bedarf Nullen ein:Format Eingabedatum Ergebnis 0 17.4.2014 "17.04.2014" 1 17.4.2014 "04.2014" 1 8.11.2014 "11.2014" 2 17.04.2014 "2014" */BEGIN DECLARE @res nvarchar(255); DECLARE @day int=DAY(@dt); ERKLÄRE @Monat int=MONAT(@dt); DECLARE @year int=YEAR(@dt); if(@format=0) begin set @res=IIF(@day<10,'0'+cast(@day as nvarchar(1)), cast(@day as nvarchar(2)))+'.'; set @example@sqldat.com+IIF(@month<10,'0'+cast(@month as nvarchar(1)), cast(@month as nvarchar(2)))+'.'; setze @example@sqldat.com+cast(@year als nvarchar(255)); end else if(@format=1) begin set @res=IIF(@month<10,'0'+cast(@month as nvarchar(1)), cast(@month as nvarchar(2)))+'. '; setze @example@sqldat.com+cast(@year als 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, // Eingabezeit @format int=0 // voreingestelltes Format)RETURNS nvarchar(255)AS/* Gibt zurück time als String entsprechend dem angegebenen Format und der eingegebenen Uhrzeit Fügt bei Bedarf Nullen ein:format input time result 0 17:04 "17:04:00" 1 17:04 "17:04" 1 8:04 "08:04 " 2 17:04 "17"*/BEGIN DECLARE @res nvarchar(255); DECLARE @hour int=DATEPART(HOUR, @dt); DECLARE @min int=DATEPART(MINUTE, @dt); DECLARE @sec int=DATEPART(SECOND, @dt); if(@format=0) begin set @res=IIF(@hour<10,'0'+cast(@hour as nvarchar(1)), cast(@hour as nvarchar(2)))+':'; set @example@sqldat.com+IIF(@min<10,'0'+cast(@min as nvarchar(1)), cast(@min as nvarchar(2)))+':'; set @example@sqldat.com+IIF(@sec<10,'0'+cast(@sec as nvarchar(1)), cast(@sec as 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 @example@sqldat.com+IIF(@min<10,'0'+cast(@min as nvarchar(1)), cast(@min as nvarchar(2))); end else if(@format=2) begin set @res=IIF(@hour<10,'0'+cast(@hour as nvarchar(1)), cast(@hour as nvarchar(2))); Ende RETURN @res;ENDGO[/expand]
9. Erstellen Sie eine gespeicherte Prozedur, die einen HTML-Bericht zu Nachrichten in Form einer Tabelle erstellt:
[expand title =”Code”]
USE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [srv].[GetHTMLTable] @recipients nvarchar(max) ,@dt datetime // bis zu welchem Datum gelesen wirdASBEGIN /* generiert HTML-Code für Tabelle */ SET NOCOUNT ON; Deklarieren Sie @body nvarchar(max); deklarieren Sie @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 ); Deklarieren Sie @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 into @tbl( [ERROR_TITLE] ,[ERROR_PRED_MESSAGE] ,[ERROR_NUMBER] ,[ERROR_MESSAGE] ,[ERROR_LINE] ,[ERROR_PROCEDURE] ,[ERROR_POST_MESSAGE ] ,[InsertDate] ,[StartDate] ,[FinishDate] ,[Count] ) Top 100 auswählen [ERROR_TITLE] ,[ERROR_PRED_MESSAGE] ,[ERROR_NUMBER] ,[ERROR_MESSAGE] ,[ERROR_LINE] ,[ERROR_PROCEDURE] ,[ERROR_POST_MESSAGE] ,[InsertDate] ,[StartDate] ,[FinishDate] ,[Count] from [srv].[ErrorInfo] where ([RECIPIENTS]example@sqldat.com ) oder (@recipients IS NULL) und InsertDate" setzen;="" setze="" @example@sqldat.com+' '; set @example@sqldat.com+''; set @example@sqldat.com+'№ п/п'; setze @example@sqldat.com+''; set @example@sqldat.com+''; setze @beispiel@sqldat.com+'DATUM'; setze @example@sqldat.com+''; set @example@sqldat.com+''; set @example@sqldat.com+'FEHLER'; setze @example@sqldat.com+''; set @example@sqldat.com+''; set @example@sqldat.com+'BESCHREIBUNG'; setze @example@sqldat.com+''; set @example@sqldat.com+''; setze @example@sqldat.com+'FEHLERCODE'; setze @example@sqldat.com+''; set @example@sqldat.com+''; setze @example@sqldat.com+'NACHRICHT'; setze @example@sqldat.com+''; set @example@sqldat.com+''; setze @example@sqldat.com+'START'; setze @example@sqldat.com+''; set @example@sqldat.com+''; setze @example@sqldat.com+'FINISH'; setze @example@sqldat.com+''; set @example@sqldat.com+''; setze @example@sqldat.com+'ZAHL'; setze @example@sqldat.com+''; set @example@sqldat.com+''; set @example@sqldat.com+'LINE NUMBER'; setze @example@sqldat.com+''; set @example@sqldat.com+''; set @example@sqldat.com+'VERFAHREN'; setze @example@sqldat.com+''; set @example@sqldat.com+''; set @example@sqldat.com+'HINWEIS'; setze @example@sqldat.com+''; setze @example@sqldat.com+''; while((select top 1 1 from @tbl)>0) begin set @example@sqldat.com+''; Auswahl oben 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 @example@sqldat.com+''; setze @example@sqldat.com+cast(@ID als nvarchar(max)); setze @example@sqldat.com+''; set @example@sqldat.com+''; set @example@sqldat.com+rep.GetDateFormat(@InsertDate, default)+' '+rep.GetTimeFormat(@InsertDate, default); // cast(@InsertDate as nvarchar(max)); setze @example@sqldat.com+''; set @example@sqldat.com+''; set @example@sqldat.com+isnull(@ERROR_TITLE,''); setze @example@sqldat.com+''; set @example@sqldat.com+''; set @example@sqldat.com+isnull(@ERROR_PRED_MESSAGE,''); setze @example@sqldat.com+''; set @example@sqldat.com+''; set @example@sqldat.com+isnull(@ERROR_NUMBER,''); setze @example@sqldat.com+''; set @example@sqldat.com+''; set @example@sqldat.com+isnull(@ERROR_MESSAGE,''); setze @example@sqldat.com+''; set @example@sqldat.com+''; set @example@sqldat.com+rep.GetDateFormat(@StartDate, default)+' '+rep.GetTimeFormat(@StartDate, default); //cast(@StartDate as nvarchar(max)); setze @example@sqldat.com+''; set @example@sqldat.com+''; set @example@sqldat.com+rep.GetDateFormat(@FinishDate, default)+' '+rep.GetTimeFormat(@FinishDate, default); //cast(@FinishDate as nvarchar(max)); setze @example@sqldat.com+''; set @example@sqldat.com+''; set @example@sqldat.com+cast(@Count as nvarchar(max)); setze @example@sqldat.com+''; set @example@sqldat.com+''; set @example@sqldat.com+isnull(@ERROR_LINE,''); setze @example@sqldat.com+''; set @example@sqldat.com+''; set @example@sqldat.com+isnull(@ERROR_PROCEDURE,''); setze @example@sqldat.com+''; set @example@sqldat.com+''; set @example@sqldat.com+isnull(@ERROR_POST_MESSAGE,''); setze @example@sqldat.com+''; löschen aus @tbl wo example@sqldat.com; setze @example@sqldat.com+''; end set @example@sqldat.com+''; Wählen Sie @body;ENDGO [/expand]
10. Erstellen Sie eine gespeicherte Prozedur, die Nachrichten sendet:
[expand title =”Code”]
USE [DATABAE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [srv].[RunErrorInfoProc] @IsRealTime bit =0 // Sendemodus (1-Echtzeit)ASBEGIN /* Fehlerbenachrichtigungen mit dem angegebenen Modus senden */ SET NOCOUNT ON; @dt datetime=getdate(); @tbl-Tabelle deklarieren (Empfänger nvarchar(max)); @Empfänger deklarieren nvarchar(max); deklarieren Sie @recipient nvarchar (255); @result deklarieren nvarchar(max)=''; @recp deklarieren nvarchar(max); deklarieren Sie @ind int; @recipients_key deklarieren nvarchar(max); // alle notwendigen Nachrichten empfangen in @tbl(Recipients) einfügen select [RECIPIENTS] from srv.ErrorInfo where InsertDate0) begin //Empfänger empfangen select top (1) @recipients=Recipients from @tbl; setze @example@sqldat.com; set @result=''; // für jeden Empfänger 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)example@sqldat.com); end else begin set @example@sqldat.com; setze @empfänger=''; Ende; // Empfänger-E-Mails empfangen exec [srv].[GetRecipients] @example@sqldat.com, @example@sqldat.com out; if(len(@recp)=0) begin exec [srv].[GetRecipients] @example@sqldat.com, @example@sqldat.com out; if(len(@recp)=0) set @example@sqldat.com; Ende // getrennt durch Symbol ';' set @example@sqldat.comexample@sqldat.com+';'; end set @result=substring(@result,1,len(@result)-1); setze @example@sqldat.com; // HTML-Bericht mit den angegebenen Empfängern empfangen und Datum einfügen in @rec_body(Body) exec srv.GetHTMLTable @example@sqldat.com_key, @example@sqldat.com; // HTML-Bericht empfangen select top (1) @body=Body from @rec_body; // der eigentliche sendende EXEC msdb.dbo.sp_send_dbmail // E-Mail-Versand des von uns erstellten Admin-Profils @profile_name ='ALARM', // Empfänger-E-Mail @recipients =@recipients, // Text einer Nachricht @body =@body, // Betreff @subject =N'INFORMATION ON EXECUTION ERRORS', @body_format='HTML'--, // Lassen Sie uns beispielsweise die Ergebnisse einer zufälligen SQL-Abfrage zur Nachricht example@sqldat.com =@query--'SELECT TOP hinzufügen 10 name FROM sys.objects'; löschen aus @tbl wo example@sqldat.com_key; aus @rec_body löschen; end // die gesendeten Nachrichten archivieren INSERT INTO [srv].[ErrorInfoArchive] ([ErrorInfo_GUID] ,[ERROR_TITLE] ,[ERROR_PRED_MESSAGE] ,[ERROR_NUMBER] ,[ERROR_MESSAGE] ,[ERROR_LINE] ,[ERROR_PROCEDURE] ,[ERROR_POST_MESSAGE] ,[ RECIPIENTS] ,[StartDate] ,[FinishDate] ,[Count] ,IsRealTime ) SELECT [ErrorInfo_GUID] ,[ERROR_TITLE] ,[ERROR_PRED_MESSAGE] ,[ERROR_NUMBER] ,[ERROR_MESSAGE] ,[ERROR_LINE] ,[ERROR_PROCEDURE] ,[ERROR_POST] [RECIPIENTS] ,[StartDate] ,[FinishDate] ,[Count] ,IsRealTime FROM [srv].[ErrorInfo] where example@sqldat.com and InsertDate [/expand]
Diese gespeicherte Prozedur nimmt jede Nachricht aus der Nachrichtenwarteschlange und verpackt sie in einen HTML-Bericht in Form einer Tabelle. Für Empfänger wird basierend auf ihrem Code oder ihrer primären E-Mail-Adresse eine Zeichenfolge erstellt, die aus E-Mail-Adressen besteht, an die eine Nachricht gesendet wird. Auf diese Weise werden alle ausgewählten Nachrichten verarbeitet. Hier wird die gespeicherte Prozedur msdb.dbo.sp_send_dbmail verwendet.
11. Erstellen Sie zwei Aufgaben im Agenten (die erste ist für Echtzeitbenachrichtigungen (1 Mal pro Minute geplant), die zweite für einfache Benachrichtigungen (1 Mal pro Stunde geplant)). Fügen Sie dem Code der Aufgabe Folgendes hinzu:
EXECUTE [DATENBANKNAME].[srv].[RunErrorInfoProc] @IsRealTime=0; // 0 - für einfache Nachrichten und 1 - für EchtzeitnachrichtenHier ist ein Beispiel für die Fehlerberichterstattung:
[expand title="Code"]
begin try exec [DATABASE_NAME].[srv].[KillFullOldConnect];end trybegin catch deklariere @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)='LÖSCHEN NICHT ANTWORTENDER PROZESSE AUF DEM SERVER' Beispiel @sqldat.com@servername, @str_pred_mess nvarchar(max)='DER FEHLER BEIM LÖSCHEN VON NICHT ANTWORTENDEN PROZESSEN IST AUF DEM SERVER 'example@sqldat.com@servername+' aufgetreten'; exec [DATENBANKNAME].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, @ EMPFÄNGER ='EMPFÄNGER1;EMPFÄNGER2'; Erklären Sie @err example@sqldat.com@error; raiserror(@str_mess,16,1);end catch[/expand]
Hier wird die gespeicherte Prozedur svr.KillFullOldConnect verwendet.
Ergebnis
Dieser Artikel enthält ein Beispiel für die Erweiterung der Funktionalität einer regulären Datenbank-E-Mail und ein Beispiel dafür, wie Benachrichtigungen in HTML-Tabellen generiert und dann per E-Mail an Administratoren gesendet werden. Dieser Ansatz ermöglicht es, Administratoren in Echtzeit oder nach einer bestimmten Zeit über verschiedene Probleme zu benachrichtigen, wodurch das Auftreten eines kritischen Problems und des Ausfalls von DBMS und Server minimiert wird, was wiederum die Produktion vor Verzögerungen im Arbeitsablauf schützt.
Referenzen:
- Sp_send_dbmail
- Datenbank-Mail
- Srv.KillFullOldConnect