Отправка электронной почты с сервера SQL для каждой строки набора данных
Я создал хранимую процедуру для отправки напоминания по электронной почте группе сотрудников каждую неделю. Агент сервера SQL запускает запланированную процедуру каждую неделю, которая создает набор данных о сотрудниках за эти недели, и затем мне нужно, чтобы каждый из сотрудников получил электронное письмо, но я не могу использовать хранимый процесс электронной почты в соответствии с запланированным оператором SELECT.
Это было бы возможно с помощью функции, но я использую EXEC msdb.dbo.sp_send_dbmail для отправки почты, которая не может быть выполнена в функции.
1 ответ
Используйте хранимую процедуру. Внутри хранимой процедуры используйте курсор, чтобы получить информацию об электронном письме и о том, что вы хотите отправить. Повторно вызывайте sp_send_dbmail, пока все сотрудники не получат электронное письмо.
Ладно, мне понадобилось несколько минут, чтобы настроить базу данных тестовых случаев. Мы отправляем электронные письма Скотту Адамсу, Дейву Леттерману и Биллу Гейтсу.
/*
Setup test database.
*/
-- Use master
USE [master]
GO
-- Create a simple database using models attributes
CREATE DATABASE [MAIL];
GO
-- Use mail
USE [MAIL]
GO
-- Drop existing
IF OBJECT_ID(N'[DBO].[EMAIL_LIST]') > 0
DROP TABLE [DBO].[EMAIL_LIST]
GO
-- Create new
CREATE TABLE [DBO].[EMAIL_LIST]
(
ID INT IDENTITY(1,1) PRIMARY KEY,
EMAIL_ADDRESS VARCHAR(64),
EMAIL_SUBJ VARCHAR(64),
EMAIL_BODY VARCHAR(256),
SENT_FLAG TINYINT DEFAULT (0)
);
-- Insert simple data
INSERT INTO [DBO].[EMAIL_LIST] (EMAIL_ADDRESS, EMAIL_SUBJ, EMAIL_BODY)
VALUES
('scottadams@aol.com','Dilbert','What''s up scott?'),
('lateshow@pipeline.com','Late Show','Please read this letter Dave.'),
('billg@microsoft.com','Gates','How''s the weather in Seatle?');
-- Show the data
SELECT * FROM [DBO].[EMAIL_LIST];
Эта хранимая процедура считывает список неотправленных писем и отправляет их.
/*
Create stored procedure
*/
-- Drop existing
IF OBJECT_ID(N'[DBO].[SEND_EMAILS]') > 0
DROP PROCEDURE [DBO].[SEND_EMAILS]
GO
-- Create new
CREATE PROCEDURE [dbo].[SEND_EMAILS]
AS
BEGIN
-- Error handling variables
DECLARE @err_number int;
DECLARE @err_line int;
DECLARE @err_message varchar(2048);
DECLARE @err_procedure varchar(2048);
-- ** Error Handling - Start Try **
BEGIN TRY
-- No counting of rows
SET NOCOUNT ON;
-- Declare variables
DECLARE @VAR_ADDRESS VARCHAR(64);
DECLARE @VAR_SUBJ VARCHAR(64);
DECLARE @VAR_BODY varchar(256);
-- Get email list
DECLARE VAR_CURSOR CURSOR FOR
SELECT EMAIL_ADDRESS, EMAIL_SUBJ, EMAIL_BODY
FROM [DBO].[EMAIL_LIST]
WHERE SENT_FLAG = 0;
-- Open cursor
OPEN VAR_CURSOR;
-- Get first row
FETCH NEXT FROM VAR_CURSOR
INTO @VAR_ADDRESS, @VAR_SUBJ, @VAR_BODY;
-- While there is data
WHILE (@@fetch_status = 0)
BEGIN
-- Send the email
EXEC msdb.dbo.sp_send_dbmail
@recipients = @VAR_ADDRESS,
@subject = @VAR_SUBJ,
@body = @VAR_BODY,
@body_format = 'HTML' ;
-- Grab the next record
FETCH NEXT FROM VAR_CURSOR
INTO @VAR_ADDRESS, @VAR_SUBJ, @VAR_BODY;
END
-- Close cursor
CLOSE VAR_CURSOR;
-- Release memory
DEALLOCATE VAR_CURSOR;
-- Update the table as processed
UPDATE [DBO].[EMAIL_LIST]
SET SENT_FLAG = 1
WHERE SENT_FLAG = 0;
-- ** Error Handling - End Try **
END TRY
-- ** Error Handling - Begin Catch **
BEGIN CATCH
-- Grab variables
SELECT
@err_number = ERROR_NUMBER(),
@err_procedure = ERROR_PROCEDURE(),
@err_line = ERROR_LINE(),
@err_message = ERROR_MESSAGE();
-- Raise error
RAISERROR ('An error occurred within a user transaction.
Error Number : %d
Error Message : %s
Affected Procedure : %s
Affected Line Number: %d'
, 16, 1
, @err_number, @err_message, @err_procedure, @err_line);
-- ** Error Handling - End Catch **
END CATCH
END
Глядя на таблицу MSDB.[Dbo].[Sysmail_mailitems], мы видим, что элементы были поставлены в очередь. Это зависит от того, настроена ли почта базы данных с общедоступным профилем по умолчанию.
Планирование хранимой процедуры с помощью задания зависит от вас.