Отправка электронной почты с сервера SQL для каждой строки набора данных

Я создал хранимую процедуру для отправки напоминаний по электронной почте группе сотрудников каждую неделю. Агент SQL-сервера каждую неделю запускает запланированную процедуру, которая создает набор данных о сотрудниках за эту неделю, а затем мне нужно, чтобы каждый из сотрудников получил электронное письмо, но я не могу использовать хранимую электронную почту процедуру, встроенную в запланированный оператор SELECT.

Это было бы возможно с помощью функции, но я использую EXEC msdb.dbo.sp_send_dbmail для отправки почты, которая не может быть выполнена в функции.


person defect833    schedule 20.01.2014    source источник
comment
Это было бы довольно просто с .net или ColdFusion или подобными приложениями. Это не доступно?   -  person Dan Bracuk    schedule 21.01.2014
comment
Это должно быть полностью автоматизировано по расписанию, поэтому лучше всего использовать агент SQL-сервера.   -  person defect833    schedule 21.01.2014


Ответы (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
('[email protected]','Dilbert','What''s up scott?'),
('[email protected]','Late Show','Please read this letter Dave.'),
('[email protected]','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], мы видим, что элементы были поставлены в очередь для отправки. Это зависит от того, настроена ли почта базы данных с общедоступным профилем по умолчанию.

введите здесь описание изображения

Планирование хранимой процедуры через задание зависит от вас.

person CRAFTY DBA    schedule 20.01.2014