Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Konfigurowanie powiadomień o poczcie bazy danych w MS SQL Server

Wprowadzenie

Często istnieje potrzeba poinformowania w jakiś sposób administratorów o problemach z serwerem. Powiadomienia są generalnie podzielone na 2 typy:

1) powiadomienia w czasie rzeczywistym, czyli takie, które muszą nadejść natychmiast po wystąpieniu problemu

2) opóźnione powiadomienia, czyli takie, które pojawiają się po dość długim czasie (ponad 1 godzina) od wystąpienia problemu.

W mojej pracy konieczne było rozszerzenie funkcjonalności zwykłej poczty bazy danych SQL Server.

W tym artykule rozważymy przykład generowania powiadomień w tabelach HTML, a następnie wysyłania ich do administratorów.

Rozwiązanie

1. Skonfiguruj pocztę bazy danych

2. Utwórz tabelę dla odbiorców:

[rozwiń tytuł ="Kod"]

 USE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[Odbiorca]( [Recipient_GUID] [unikalny identyfikator] ROWGUIDCOL NOT NULL, [Recipient_Name] [nvarchar](255) NOT NULL, // podstawowy adres e-mail odbiorcy Recipient_Code] [nvarchar](10) NOT NULL, // kod odbiorcy [IsDeleted] [bit] NOT NULL, // wskaźnik usunięcia (czy odbiorca jest używany czy nie) [InsertUTCDate] [datetime] NOT NULL, CONSTRAINT [PK_Recipient ] PRIMARY KEY CLUSTERED ( [Recipient_GUID] ASC) Z (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY], CONSTRAINT [AK_EDSC_Code odbiorca_LUS] (PAD_INDEX =WYŁĄCZONE, STATISTICS_NORECOMPUTE =WYŁĄCZONE, IGNORE_DUP_KEY =WYŁĄCZONE, ALLOW_ROW_LOCKS =WŁĄCZONE, ALLOW_PAGE_LOCKS =WŁĄCZONE) WŁĄCZONE [PRIMARY], OGRANICZENIE [AK_Recipient_Name] UNIKALNE NIESKLASTERZOWANE ([Nazwa_odbiorcy] ASC) Z ISTNIEJĄCĄ =WYŁĄCZONE_PAD_MP F, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY] TABELA GOALTERÓW [srv]. [Odbiorca] DODAJ OGRANICZENIE [DF_Recipient_Recipient_GUID] DEFAULT (nowy identyfikator()) TABELA GUID [GOALTER_GUID] srv].[Odbiorca] DODAJ OGRANICZENIE [DF_Recipient_IsDeleted] DOMYŚLNE ((0)) DLA [IsDeleted]TABELA BRAMKARÓW [srv].[Odbiorca] DODAJ OGRANICZENIE [DF_Recipient_InsertUTCDate] DOMYŚLNE (getutcdate()) DLA [GO[/expand]

3. Utwórz tabelę adresów odbiorców:

[rozwiń tytuł ="Kod"]

UŻYJ [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv]. [Adres]( [Address_GUID] [unikalny identyfikator] ROWGUIDCOL NIE NULL, [Recipient_GUID] [unikalny identyfikator] NIE NULL, // var [adres] (n 255) NIE NULL, // e-mail [IsDeleted] [bit] NIE NULL, // wskaźnik usunięcia (niezależnie od tego, czy e-mail jest używany, czy nie) [InsertUTCDate] [data i godzina] NIE NULL, OGRANICZENIE [Adres_PK] KLASTRA KLUCZ PODSTAWOWY ( [Address_GUID] ASC ) Z (PAD_INDEX =WYŁĄCZONE, STATISTICS_NORECOMPUTE =WYŁĄCZONE, IGNORE_DUP_KEY =WYŁĄCZONE, ALLOW_ROW_LOCKS =WŁĄCZONE, ALLOW_PAGE_LOCKS =WŁĄCZONE) WŁĄCZONE [PRIMARY], OGRANICZENIE [AK_Address] UNIKALNE NIEROZKLEJONE ([Recipient_GUID] ASC)_WIEX =(Adres) , STATISTICS_NORECOMPUTE =OFF, IGNORE_DUP_KEY =OFF, ALLOW_ROW_LOCKS =ON, ALLOW_PAGE_LOCKS =ON) ON [PRIMARY]) ON [PRIMARY] TABELA GOALTERÓW [srv]. TABELA BRAMKARZA [ srv].[Adres] DODAJ OGRANICZENIE [DF_Address_IsDeleted] DOMYŚLNE ((0)) DLA [IsDeleted]TABELA GOALTERÓW [srv].[Adres] DODAJ OGRANICZENIE [DF_Address_InsertUTCDate] DOMYŚLNE (getutcdate()) DLA [InsertUTCDate]GO

[/expand]

4. Utwórz tabelę dla kolejki wiadomości:

[rozwiń tytuł ="Kod"]

UŻYJ [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv].[ErrorInfo]( [ErrorInfo_GUID] [unikalny identyfikator] NOT NULL, [ERROR_TITLE] [nvarchar](max) NULL, //AGE_title [_varMOR] (maks.) NULL, // wstępne informacje [ERROR_NUMBER] [nvarchar](maks.) NULL, // komunikat (błędu) kod [ERROR_MESSAGE] [nvarchar](maks.) NULL, // komunikat [ERROR_LINE] [nvarchar](maks.) NULL, // numer wiersza [ERROR_PROCEDURE] [nvarchar](max) NULL, // procedura składowana [ERROR_POST_MESSAGE] [nvarchar](max) NULL, // informacje wyjaśniające [RECIPIENTS] [nvarchar](max) NULL, // recipints oddzielone ';' [InsertDate] [datetime] NOT NULL, [StartDate] [datetime] NOT NULL, // data i godzina rozpoczęcia [DataZakończenia] [datatime] NOT NULL, // data i godzina zakończenia [Count] [int] NOT NULL, // liczba razy [Data aktualizacji] [dat etime] NOT NULL, [IsRealTime] [bit] NOT NULL, // wskaźnik czasu rzeczywistego [InsertUTCDate] [datetime] NULL, CONSTRAINT [PK_ErrorInfo] KLUCZ PODSTAWOWY ([ErrorInfo_GUID] ASC) Z (PAD_INDEX =OFF, STATISTICS_NORECOMPUTE =OFF IGNORE_DUP_KEY =WYŁ, ALLOW_ROW_LOCKS =WŁ, ALLOW_PAGE_LOCKS =WŁ) WŁ [PRIMARY]) WŁ [PRIMARY] TEXTIMAGE_ON [PRIMARY]TABELA GOALTERÓW [srv].[ErrorInfo] DODAJ OGRANICZENIE [DF_ErrorInfo_ErrorInfo_GUIDneorGO] DEFA TABELA [srv].[ErrorInfo] DODAJ OGRANICZENIE [DF_ErrorInfo_InsertDate] DOMYŚLNE (getdate()) DLA [InsertDate] TABELA BRAMKARÓW [srv].[ErrorInfo] DODAJ OGRANICZENIE [DF_ErrorInfo_StartDate] DOMYŚLNE (getdate()) DLA [StartDate]GOAL srv].[ErrorInfo] DODAJ OGRANICZENIE [DF_ErrorInfo_FinishDate] DOMYŚLNE (getdate()) DLA [FinishDate]TABELI BRAMKARÓW [srv].[ErrorInfo] DODAJ OGRANICZENIE [DF_ErrorInfo_Count] DOMYŚLNE ((1)) DLA [Count]TABELI BRAMKARÓW [srv] .[ErrorInfo] DODAJ OGRANICZENIE [DF__ErrorInfo__Updat__5FFEE747] DEFAU LT (getdate()) DLA [UpdateDate]TABELI BRAMKARÓW [srv].[ErrorInfo] DODAJ OGRANICZENIE [DF_ErrorInfo_IsRealTime] DOMYŚLNE ((0)) DLA [IsRealTime]TABELI BRAMKARÓW [srv].[ErrorInfo] DODAJ OGRANICZENIE [DF_ErrorInfo_IsRealTime] DEFAUT getutcdate()) DLA [InsertUTCDate]GO

[/expand]

5. Utwórz tabelę archiwum dla wiadomości wysłanych z kolejki wiadomości:

[rozwiń tytuł ="Kod"]

UŻYJ [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABELA [srv]. [ErrorInfoArchive] ( [ErrorInfo_GUID] [unikalny identyfikator] ROWGUIDCOL NIE NULL, [BŁĄD_TYTUŁ] [nvarchar,(nULLER](MARESSOR) NULL ) NULL, [ERROR_NUMBER] [nvarchar](maks.) NULL, [ERROR_MESSAGE] [nvarchar](maks.) NULL, [ERROR_LINE] [nvarchar](maks.) NULL, [ERROR_PROCEDURE] [nvarchar](maks.) 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] KLUCZ PODSTAWOWY ([ErrorInfo_GUID] ASC) Z (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 TABELA R [srv]. [ErrorInfoArchive] DODAJ OGRANICZENIE [DF_ErrorInfoArchive_ErrorInfo_GUID] DOMYŚLNE (newsectionid()) DLA [ErrorInfo_GUID]TABELI GOALTERÓW [srv].[ErrorInfoArchive] DODAJ OGRANICZENIE [DF_ArchiveErrorInfo_GUID] (NERRORGATEERT) TABLES DEFATED [srv].[ErrorInfoArchive] DODAJ OGRANICZENIE [DF_ErrorInfoArchive_StartDate] DOMYŚLNE (getdate()) DLA [Data początkowa]TABELI BRAMKARÓW [srv].[ErrorInfoArchive] DODAJ OGRANICZENIE [DF_ErrorInfoArchive_FinishDate] DEFAULTrGOALTERFigetDTABLE [srv].[ErrorInfoArchive] DODAJ OGRANICZENIE [DF_ErrorInfoArchive_FinishDate] ].[ErrorInfoArchive] DODAJ OGRANICZENIE [DF_ErrorInfoArchive_Count] DOMYŚLNE ((1)) DLA [Count]TABELA BRAMKARÓW [srv].[ErrorInfoArchive] DODAJ OGRANICZENIE [DF_ErrorInfoArchive_UpdateDate] DOMYŚLNE (getdate()) DLA [UpdateDate]GOAL [ErrorInfoArchive] DODAJ OGRANICZENIE [DF_ErrorInfoArchive_IsRealTime] DOMYŚLNE ((0)) DLA [IsRealTime] TABELI BRAMKARÓW [srv]. [ErrorInfoArchive] DODAJ OGRANICZENIE [DF_ErrorInfoArchive_InsertUTCDate] DOMYŚLNE (CD)pIngotcdate()) ponownie> 

[/expand]

Te informacje są potrzebne do tworzenia historii. Poza tym ta tabela musi zostać usunięta z bardzo starych danych (na przykład starszych niż miesiąc).

6. Utwórz procedurę składowaną, która rejestruje nową wiadomość w kolejce wiadomości:

[rozwiń tytuł ="Kod"]

UŻYJ [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [srv].[ErrorInfoIncUpd] @ERROR_TITLE nvarchar(max), @ERROR_PRED_MESSAGE nvarchar(max), @varAGEROROR_max ), @varAGERROR_LINE nvarchar(max), @ERROR_PROCEDURE nvarchar(max), @ERROR_POST_MESSAGE nvarchar(max), @RECIPIENTS nvarchar(max), @StartDate datetime=null, @FinishDate datetime=null, @IsRealTime bit =0ASBEGIN /* Błąd podczas logowania tabela do wysłania e-mailem, jeśli w tabeli jest już wpis o tym samym tytule, treści i nadawcy, zmieni się data zakończenia błędu, data aktualizacji rekordu oraz liczba błędów */ USTAW NR. NA; zadeklaruj unikalny identyfikator @ErrorInfo_GUID; wybierz top 1 @ErrorInfo_GUID=ErrorInfo_GUID z srv.ErrorInfo gdzie (example@sqldat.com_TITLE lub @ERROR_TITLE ma wartość null) i example@sqldat.com i (example@sqldat.com_MESSAGE lub @ERROR_MESSAGE ma wartość null) i (przykład@sqldat_AGE_s) lub @ERROR_PRED_MESSAGE ma wartość null) i (example@sqldat.com_POST_MESSAGE lub @ERROR_POST_MESSAGE ma wartość null) i (example@sqldat.com lub @IsRealTime ma wartość null); if (@ERRORINFO_GUID IS NULL) Rozpocznij wstaw do srv.errorinfo (błąd_title, error_pred_message, error_number, error_message, error_line, error_procedure, error_post_message, odbiorcy, isrealtime, steralDate, FinansDate) Wybierz @error_title,@error_pred_message, error_number, error_numer, error_number, error_message, ERROR_LINE ,@ERROR_PROCEDURE ,@ERROR_POST_MESSAGE ,@RECIPIENTS ,@IsRealTime ,isnull(@StartDate, getdate()) ,isnull(@FinishDate,getdate()) end else rozpocznij aktualizację srv.ErrorInfo set FinishDate=getdate(), [Count]=[Count]+1, UpdateDate=getdate() gdzie example@sqldat.com_GUID; koniecENDGO

[/expand]

7. Utwórz procedurę składowaną, która zwraca ciąg z adresów według kodu lub podstawowego adresu e-mail odbiorcy:

[rozwiń tytuł ="Kod"]

UŻYJ [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER PROCEDURA ONGOCREATE [srv].[GetRecipients]@Nazwa_odbiorcy nvarchar(255)=NULL,@Kod_odbiorcy nvarchar(10)=NULL,@zmienna*Procedura(max) n tworzenie powiadomień e-mail*/ASBEGIN SET NOCOUNT ON; ustaw @Odbiorcy=''; wybierz @example@sqldat.com+d.[Adres]+';' from srv.Recipient jako r inner join srv.[Adres] jako d na r.Recipient_GUID=d.Recipient_GUID gdzie (przykład@sqldat.com_Name lub @Recipient_Name JEST NULL) i (przykład@sqldat.com_Code lub @Recipient_Code JEST NULL) oraz r.IsDeleted=0 i 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. Utwórz niezbędne funkcje do pracy z datami i godzinami:

[rozwiń tytuł ="Kod"]

UŻYJ [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE FUNCTION [rep].[GetDateFormat] ( @dt datetime, // data wejściowa @format int=0 // ustawiony format) ZWRACA nvarchar(255)AS/* Zwraca datę jako ciąg znaków zgodnie z podanym formatem i datą wejścia W razie potrzeby wstawia zera:format data wejścia wynik 0 17.4.2014 "17.04.2014" 1 17.4.2014 "04.2014" 1 8.11.2014 "11.2014" 2 17.04.2014 "2014" */POCZĄTEK ZGŁOSZENIA @res nvarchar(255); ZADEKLARUJ @dzień int=DZIEŃ(@dt); ZADEKLARUJ @miesiąc int=MIESIĄC(@dt); ZADEKLARUJ @rok int=ROK(@dt); if(@format=0) rozpocznij ustaw @res=IIF(@day<10,'0'+cast(@day as nvarchar(1)), cast(@day as nvarchar(2)))+'.'; set @example@sqldat.com+IIF(@miesiąc<10,'0'+cast(@miesiąc jako nvarchar(1)), rzut(@miesiąc jako nvarchar(2)))+'.'; ustaw @example@sqldat.com+cast(@year as nvarchar(255)); end else if(@format=1) begin set @res=IIF(@month<10,'0'+cast(@month as nvarchar(1)), cast(@month as nvarchar(2)))+'. '; ustaw @example@sqldat.com+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/* Zwraca czas jako ciąg zgodnie z podanym formatem i czasem wejścia Wstawia zera tam, gdzie to konieczne:format czasu wejścia wynik 0 17:04 "17:04:00" 1 17:04 "17:04" 1 8:04 "08:04 " 2 17:04 "17"*/POCZĄTEK ZGŁOSZENIA @res nvarchar(255); ZADEKLARUJ @godzina int=DATACZĘŚĆ(GODZINA, @dt); ZADEKLARUJ @min int=DATACZĘŚĆ(MINUTA, @dt); ZADEKLARUJ @sec int=DATACZĘŚĆ(DRUGA, @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 jako nvarchar(1)), rzut(@min jako nvarchar(2)))+':'; ustaw @example@sqldat.com+IIF(@sec<10,'0'+cast(@sec jako nvarchar(1)), cast(@sec jako nvarchar(2))); end else if(@format=1) begin set @res=IIF(@hour<10,'0'+cast(@hour as nvarchar(1)), cast(@hour as nvarchar(2)))+':'; ustaw @example@sqldat.com+IIF(@min<10,'0'+cast(@min jako nvarchar(1)), cast(@min jako nvarchar(2))); end else if(@format=2) begin set @res=IIF(@hour<10,'0'+cast(@hour as nvarchar(1)), cast(@hour as nvarchar(2))); koniec RETURN @res;ENDGO

[/expand]

9. Utwórz procedurę składowaną, która tworzy raport HTML dotyczący wiadomości w formie tabeli:

[rozwiń tytuł ="Kod"]

UŻYJ [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [srv].[GetHTMLTable] @recipients nvarchar(max) ,@dt datetime // do której daty czytać ASBEGIN /* generuje kod HTML dla tabeli */ SET NOCOUNT ON; zadeklaruj @body nvarchar(max); zadeklaruj @tbl table(ID int identity (1,1) ,[ERROR_TITLE] nvarchar(max) ,[ERROR_PRED_MESSAGE] nvarchar(max) ,[ERROR_NUMBER] nvarchar(max) ,[ERROR_MESSAGE] nvarchar(max) ,[nvarchar_LINE] (max) ,[ERROR_PROCEDURE] nvarchar(max) ,[ERROR_POST_MESSAGE] nvarchar(max) ,[InsertDate] datetime ,[StartDate] datetime ,[FinishDate] datetime ,[Count] int ); zadeklaruj @ID int ,@ERROR_TITLE nvarchar(max) ,@ERROR_PRED_MESSAGE nvarchar(max) ,@ERROR_NUMBER nvarchar(max) ,@ERROR_MESSAGE nvarchar(max) ,@ERROR_LINE nvarchar(MESSAGE) nvarchar(max) (maks.) ,@InsertDate datetime ,@StartDate datetime ,@FinishDate datetime ,@Count int wstaw do @tbl( [ERROR_TITLE] ,[ERROR_PRED_MESSAGE] ,[ERROR_NUMBER] ,[ERROR_MESSAGE] ,[ERRORERRESSORAGE]_PRO,[COS ] ,[InsertDate] ,[StartDate] ,[FinishDate] ,[Count] ) wybierz pierwszą setkę [ERROR_TITLE] ,[ERROR_PRED_MESSAGE] ,[ERROR_NUMBER] ,[ERROR_MESSAGE] ,[ERROR_LINE] ,[ERROR_PROCEDURE] ,[ERROR_POST_MESSAGE] ,[InsertDate] ,[StartDate] ,[FinishDate] ,[Count] from [srv].[ErrorInfo], gdzie ([@RECIQlDAT].com ) lub (@recipients IS NULL) i InsertDate'; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+'№ п/п'; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+'DATA'; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+'BŁĄD'; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+'OPIS'; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+'KOD BŁĘDU'; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+'WIADOMOŚĆ'; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+'START'; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+'FINISH'; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+'LICZBA'; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+'NUMER LINII'; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+'PROCEDURA'; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+'UWAGA'; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; while((wybierz top 1 1 z @tbl)>0) rozpocznij set @example@sqldat.com+''; wybierz top 1 @ID =[ID] ,@ERROR_TITLE =[ERROR_TITLE] ,@ERROR_PRED_MESSAGE=[ERROR_PRED_MESSAGE] ,@ERROR_NUMBER =[ERROR_NUMBER] ,@ERROR_MESSAGE =[ERROR_MESSAGE]_PROEDRORCELL =[ERROR_MESSAGE] =[ERROR_LINE] ] ,@ERROR_POST_MESSAGE=[ERROR_POST_MESSAGE] ,@InsertDate =[InsertDate] ,@StartDate =[StartDate] ,@FinishDate =[FinishDate] ,@Count =[Liczba] z @tbl zamówienia według daty wstawienia asc; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+cast(@ID jako nvarchar(max)); ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; set @example@sqldat.com+rep.GetDateFormat(@InsertDate, domyślnie)+' '+rep.GetTimeFormat(@InsertDate, domyślnie); // cast(@InsertDate as nvarchar(max)); ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+isnull(@ERROR_TITLE,''); ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+isnull(@ERROR_PRED_MESSAGE,''); ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+isnull(@ERROR_NUMBER,''); ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+isnull(@KOMUNIKAT_BŁĘDU,''); ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; set @example@sqldat.com+rep.GetDateFormat(@StartDate, default)+' '+rep.GetTimeFormat(@StartDate, default); //cast(@DataRozpoczęcia jako nvarchar(max)); ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; set @example@sqldat.com+rep.GetDateFormat(@FinishDate, domyślnie)+' '+rep.GetTimeFormat(@FinishDate, default); //cast(@DataZakończenia jako nvarchar(max)); ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+cast(@Count as nvarchar(max)); ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+isnull(@ERROR_LINE,''); ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+isnull(@ERROR_PROCEDURE,''); ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+''; ustaw @example@sqldat.com+isnull(@ERROR_POST_MESSAGE,''); ustaw @example@sqldat.com+''; usuń z @tbl gdzie example@sqldat.com; ustaw @example@sqldat.com+''; koniec zestawu @example@sqldat.com+''; wybierz @body;ENDGO

[/expand]

10. Utwórz procedurę składowaną, która wysyła wiadomości:

[rozwiń tytuł ="Kod"]

USE [DATABAE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [srv].[RunErrorInfoProc] @IsRealTime bit =0 // tryb wysyłania (1-w czasie rzeczywistym)ASBEGIN /* wysyłanie powiadomień o błędach w określonym trybie */ SET NOCOUNT ON; zadeklaruj @dt datetime=getdate(); zadeklaruj @tbl table(Odbiorcy nvarchar(max)); zadeklaruj @odbiorcy nvarchar(max); zadeklaruj @ odbiorca nvarchar(255); zadeklaruj @result nvarchar(max)=''; zadeklaruj @recp nvarchar(max); zadeklaruj @ind int; zadeklaruj @recipients_key nvarchar(max); // odbierz wszystkie potrzebne wiadomości wstaw do @tbl(Odbiorcy) wybierz [ODBIORCY] z srv.ErrorInfo gdzie InsertDate0) begin //odbierz odbiorców select top (1) @recipients=Recipients from @tbl; ustaw @example@sqldat.com; ustaw @wynik=''; // dla każdego odbiorcy 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); koniec inny początek ustaw @example@sqldat.com; ustaw @odbiorcy=''; koniec; // odbierz e-maile od odbiorców 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) ustaw @example@sqldat.com; koniec // oddzielone symbolem ';' ustaw @example@sqldat.comexample@sqldat.com+';'; end set @result=substring(@result,1,len(@result)-1); ustaw @example@sqldat.com; // odbierz raport HTML z określonymi odbiorcami i datą wstaw do @rec_body(Body) exec srv.GetHTMLTable @example@sqldat.com_key, @example@sqldat.com; // odbierz raport HTML select top (1) @body=Body from @rec_body; // rzeczywisty wysyłający EXEC msdb.dbo.sp_send_dbmail // e-mailowy profil administratora, który utworzyliśmy @profile_name ='ALARM', //e-mail odbiorcy @recipients =@recipients, // tekst wiadomości @body =@body, // Temat @subject =N'INFORMACJE O BŁĘDACH WYKONANIA', @body_format='HTML'--, // Na przykład dodajmy wyniki losowego zapytania SQL do wiadomości example@sqldat.com =@query--'SELECT TOP 10 nazwa Z sys.objects'; usuń z @tbl gdzie example@sqldat.com_key; usuń z @rec_body; zakończ // zarchiwizuj wysłane wiadomości INSERT INTO [srv].[ErrorInfoArchive] ([ErrorInfo_GUID] ,[ERROR_TITLE] ,[ERROR_PRED_MESSAGE] ,[ERROR_NUMBER] ,[ERROR_MESSAGE] ,[ERROR_LINE] ,[CESSROR_AGE] ODBIORCY] ,[DataRozpoczęcia] ,[DataZakończenia] ,[Liczba] ,IsRealTime ) SELECT [ErrorInfo_GUID] ,[ERROR_TITLE] ,[ERROR_PRED_MESSAGE] ,[ERROR_NUMBER] ,[ERROR_MESSAGE] ,[ERROR_MESSAGE] ,[ERROR],[ERROR_MESSAGE] [ODBIORCY] ,[DataRozpoczęcia] ,[DataZakończenia] ,[Liczba] ,IsRealTime FROM [srv].[ErrorInfo] gdzie example@sqldat.com i InsertDate 

[/expand]

Ta procedura składowana pobiera każdą wiadomość z kolejki wiadomości i umieszcza ją w raporcie HTML w formie tabeli. Dla odbiorców, na podstawie ich kodu lub podstawowego adresu e-mail, tworzy ciąg składający się z adresów e-mail, na które wysyłana jest wiadomość. W ten sposób przetwarzane są wszystkie wybrane wiadomości. Tutaj używana jest procedura składowana msdb.dbo.sp_send_dbmail.

11. Utwórz dwa zadania w Agencie (pierwsze dla powiadomień w czasie rzeczywistym (zaplanuj 1 raz na minutę), drugie dla prostych powiadomień (zaplanuj 1 raz na godzinę)). Dodaj następujące elementy do kodu zadania:

WYKONAJ [NAZWA_BAZY_DANYCH].[srv].[RunErrorInfoProc] @IsRealTime=0; // 0 - dla prostych wiadomości i 1 - dla wiadomości w czasie rzeczywistym

Oto przykład zgłaszania błędów:

[rozwiń tytuł=”Kod”]

rozpocznij wykonywanie exec [NAZWA_BAZY_DANYCH].[srv].[KillFullOldConnect];zakończ trybegin catch zadeklaruj @str_mess nvarchar(max)=KOMUNIKAT_BŁĘDU(), @str_num nvarchar(max)=cast(NUMER_BŁĘDU() jako nvarchar(max) ), @str_line nvarchar(max)=cast(ERROR_LINE() as nvarchar(max)), @str_proc nvarchar(max)=ERROR_PROCEDURE(), @str_title nvarchar(max)='USUWANIE PROCESÓW NIE ODPOWIADAJĄCYCH NA SERWERZE'przykład @sqldat.com@nazwa_serwera, @str_pred_mess nvarchar(max)='BŁĄD USUNIĘCIA PROCESÓW NIE ODPOWIADAJĄCYCH NA SERWERZE 'example@sqldat.com@nazwa_serwera+'; 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 =@ROR_PRED_MESSAGE=ODBIORCY ='ODBIORCA1;ODBIORCA2'; zadeklaruj @err example@sqldat.com@error; raiserror(@str_mess,16,1);zatrzask końcowy

[/expand]

Tutaj używana jest procedura składowana svr.KillFullOldConnect.

Wynik

Ten artykuł zawiera przykład rozszerzenia funkcjonalności zwykłej poczty bazy danych oraz przykład generowania powiadomień w tabelach HTML, a następnie wysyłania ich pocztą elektroniczną do administratorów. Takie podejście umożliwia powiadamianie administratorów o różnych problemach w czasie rzeczywistym lub po określonym czasie, minimalizując w ten sposób wystąpienie krytycznego problemu i awarii DBMS i serwera, co z kolei chroni produkcję przed opóźnieniami w przepływie pracy.

Odniesienia:

  1. Sp_send_dbmail
  2. Poczta bazy danych
  3. Srv.KillFullOldConnect

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL Server ROWCOUNT_BIG()

  2. Odwołaj się do aliasu w innym miejscu na liście WYBIERZ

  3. Zapytanie SQL „LIKE” przy użyciu „%”, gdzie kryteria wyszukiwania zawierają „%”

  4. Wybierz / wstaw wersję Upsert:czy istnieje wzorzec projektowy dla wysokiej współbieżności?

  5. 3 sposoby zwracania wierszy zawierających znaki alfanumeryczne w SQL Server