Sql Agent和数据库邮件是我需要的电子邮件提醒吗?

时间:2010-07-06 18:38:11

标签: sql sql-server-2005

我想使用ms sql 2005向我的客户发送电子邮件提醒。我想发送每天应该在午夜左右运行的提醒(当流量很低时)。

所以我认为最好的方法是通过ms sql 2005,我一直在研究sql代理和数据库邮件,但我不确定如何制作一个动态获取每个客户信息的脚本(每个客户都会有发送给他们的另一封电子邮件)。

所以我需要查询一个表来获取每个人的电子邮件地址,我需要一个查询来获取我计划发送的客户信息。

一旦我掌握了这些信息,我就需要格式化电子邮件并发送给他们(如果我有50个客户 - 将发送50个不同的自定义电子邮件)。

To:永远不同的人,From:static可能不会改变,Title-可能会永远不同,Body - 总是不同。

我的身体总是要求它是html,因为我将使用html标签。

那么有人可以给我一个淡化的例子来开始吗?我对数据库并不是那么好,并且没有非常使用ms sql 2005。

我认为我需要sql代理,因为它可以在设定的时间执行,当然还有数据库邮件将其全部发送出去。

但在那之后,这是一个很大的空白。我看过这篇文章

http://blog.netnerds.net/2008/02/create-a-basic-sql-server-2005-trigger-to-send-e-mail-alerts/

但她正在使用触发器,因此我不知道是否必须将它组合使用。

修改

以下是我试图保持简单的一些表格,以便我能够理解发生了什么,并且可能与我的最终结果不同。

Table A
id - pk - incrementing int
email - varchar(20)

Table B
TableBId  - pk - incrementing int
id - fk
title - varchar(30)
body - varchar(2000)
SendOutDate - datetime
type - varchar(5)

样本数据

Table A

Id       email
------------------
1       test@hotmail.com
2       bob@hotmail.com
3       jim@gmail.com


Table B
TableBId   Id   title          body          sendoutDate           type
---------------------------------------------------------------------------
1          1    Reminder1     <b>test</b>    12/24/2010 12:30 pm    Email
2          1    Reminder2     hello          12/25/2010 12:30 pm    Email
3          1    Reminder3     hi text        12/28/2010 11:30 pm    SMS
4          1    Reminder4     again          12/29/2010 5:00am      Both
5          2    Your Reminder  test          12/24/2010 2:30 am     Email
6          3    jim            bo            12/25/2010 11:59:59 pm   SMS

好的,在将来的版本中需要注意的几件事我想支持发送电子邮件和短信提醒,因此它们只是在不同类型的同一个表中。 “两者”意味着“电子邮件和短信”警报将被发送出去。

当然现在只需坚持使用电子邮件提醒,但我想向您展示整个故事,但我假设这些将是2个不同的操作,因此可能需要where子句。

接下来的时间日期。我想在午夜左右发出通知,所以午夜到午夜应该是24小时。

因此,如果我们从12月24日12点到12月25日12点,应该发送此范围内的所有通知,然后第二天将是12月25日到12月26日,依此类推。

我也猜测将表A和B连接在一起需要加入。然后我需要抓取数据并将其放入某些变量或其他内容。

那我该怎么写这个sp? KM说我需要循环一些东西或类似的东西。我猜我必须写一些sql类型forloop呢?

1 个答案:

答案 0 :(得分:0)

创建在您选择的时间每天运行的SQL Server代理作业。让该作业运行存储过程。在该存储过程中,您需要循环播放发送电子邮件所需的内容。每个不同的电子邮件一次迭代,调用EXEC msdb.dbo.sp_send_dbmail ...,...,..发送实际的电子邮件。除此之外,您还需要提出具体问题。您需要将收件人电子邮件地址列表构建到本地变量中,并构建一个邮件正文,但问题中没有任何详细信息我该如何解释该怎么做?

OP编辑后的

编辑更多细节:

设置表,我使用@TableVariables,因为我不想在我的测试系统上创建表,你需要创建常规表,使用适当的PK,FK,索引等。

SET NOCOUNT ON
DECLARE @EmailContacts table (EmailID      int
                             ,EmailAddress varchar(20)
                             )
INSERT @EmailContacts VALUES (1,'test@hotmail.com')
INSERT @EmailContacts VALUES (2,'bob@hotmail.com')
INSERT @EmailContacts VALUES (3,'jim@gmail.com')

DECLARE @EmailMessages table (MessageId     int
                             ,MessageType   char(1)  --FK to EmailMessageType.MessageType
                             ,EmailID       int          --FK to EmailContacts.EmailID
                             ,SendOutDate   datetime
                             ,MessageTitle  varchar(30)
                             ,MessageBody   varchar(2000)
                             )
INSERT @EmailMessages VALUES(1,'E', 1,'12/24/2010 12:30 pm'   , 'Reminder1'     ,'<b>test</b>')
INSERT @EmailMessages VALUES(2,'E', 1,'12/24/2010 12:30 pm'   , 'Reminder2'     ,'hello'      ) --<<changed date so there would be multiple to loop over
INSERT @EmailMessages VALUES(3,'S', 1,'12/28/2010 11:30 pm'   , 'Reminder3'     ,'hi text'    )
INSERT @EmailMessages VALUES(4,'B', 1,'12/29/2010 5:00 am'    , 'Reminder4'     ,'again'      )
INSERT @EmailMessages VALUES(5,'E', 2,'12/24/2010 2:30 am'    , 'Your Reminder' ,'test'       )
INSERT @EmailMessages VALUES(6,'S', 3,'12/25/2010 11:59:59 pm', 'jim'           ,'bo'         )

DECLARE @EmailMessageTypes table (MessageType           char(1)
                                 ,MessageTpeDescription varchar(30)
                                 )
INSERT @EmailMessageTypes VALUES ('E','Email')
INSERT @EmailMessageTypes VALUES ('S','SMS')
INSERT @EmailMessageTypes VALUES ('B','Both')
SET NOCOUNT OFF

这就是存储过程中的内容

--inside the stored procedure
BEGIN TRY

    DECLARE @RunDate        datetime
           ,@ReturnValueX   int
           ,@ErrorMsg       varchar(5000)
           ,@Rows           int

    SET @RunDate='12/24/2010 12:30 pm'  --GETDATE() --<<use GETDATE() I used '12/24... so it would find the test data

    --area to process current row from loop
    DECLARE @Process_MessageId              int
           ,@Process_MessageType            char(1)
           ,@Process_MessageTpeDescription  varchar(30)
           ,@Process_EmailID                int     
           ,@Process_EmailAddress           varchar(20)     
           ,@Process_SendOutDate            datetime
           ,@Process_MessageTitle           varchar(30)
           ,@Process_MessageBody            varchar(2000)

    SET @Process_MessageId=0

    WHILE ISNULL(@Process_MessageId,-1)>=0
    BEGIN
        --get the next row to process
        SELECT
            @Process_MessageId                  =m.MessageId
                ,@Process_MessageType           =m.MessageType 
                ,@Process_MessageTpeDescription =t.MessageTpeDescription
                ,@Process_EmailID               =m.EmailID    
                ,@Process_EmailAddress          =c.EmailAddress 
                ,@Process_SendOutDate           =m.SendOutDate 
                ,@Process_MessageTitle          =m.MessageTitle
                ,@Process_MessageBody           =m.MessageBody 
            FROM @EmailMessages      m
                INNER JOIN (SELECT
                                MIN(mm.MessageId) AS MinMessageId
                                FROM @EmailMessages  mm
                                WHERE mm.MessageId>@Process_MessageId AND mm.SendOutDate>=@RunDate AND mm.SendOutDate<=DATEADD(hour,1,@RunDate)
                           ) dt ON m.MessageId=MinMessageId
                LEFT OUTER JOIN @EmailMessageTypes t ON m.MessageType=t.MessageType
                LEFT OUTER JOIN @EmailContacts     c ON m.EmailID=c.EmailID
        SELECT @Rows=@@ROWCOUNT

        IF @Rows=0
        BEGIN
            BREAK --no more rows found
        END

        --process the row
        --comment out the PRINT when it is in production, it is nice have when running it from SQL Server Management Studio, but not necessary when run from a job
        PRINT 'Sending mail, TO: '+ISNULL(@Process_EmailAddress,'null')+', SUBJECT: '+ISNULL(@Process_MessageTitle,'null')+', BODY: '+ISNULL(@Process_MessageBody,'null')
        EXECUTE @ReturnValueX = msdb.dbo.sp_send_dbmail
                                    @recipients            =@Process_EmailAddress
                                   ,@body                  =@Process_MessageBody
                                   ,@body_format           ='HTML'
                                   ,@subject               =@Process_MessageTitle
                                   ,@profile_name          ='YourEmailProfile'

        IF @ReturnValueX!=0
        BEGIN
            SET @ErrorMsg='Error '+ISNULL(CONVERT(varchar(30),@ReturnValueX),'unknown')+', calling msdb.dbo.sp_send_dbmail '
                                 +'   @recipients='            +ISNULL(@Process_EmailAddress  ,'null')
                                 +'  ,@body='                  +ISNULL(@Process_MessageBody   ,'null')
                                 +'  ,@body_format='           +ISNULL('HTML'                 ,'null')
                                 +'  ,@subject='               +ISNULL(@Process_MessageTitle  ,'null')
                                 +'  ,@profile_name='          +ISNULL('YourEmailProfile'     ,'null')
            RAISERROR(@ErrorMsg,16,1) --send control to the BEGIN CATCH block
        END --IF ERROR

    END --WHILE

END TRY
BEGIN CATCH

    --use your error logging method of choice here
    --INSERT INTO YourErrorLogTable (...,...,...) VALUES (...,...,...,'fatal error in '+ISNULL(OBJECT_NAME(@@PROCID), 'unknown')
    --             +' error was :'
    --             +CASE WHEN ERROR_NUMBER()     IS NOT NULL THEN 'Msg '         +CONVERT(varchar(30),   ERROR_NUMBER()     ) ELSE '' END
    --             +CASE WHEN ERROR_SEVERITY()   IS NOT NULL THEN ', Level '     +CONVERT(varchar(30),   ERROR_SEVERITY()   ) ELSE '' END
    --             +CASE WHEN ERROR_STATE()      IS NOT NULL THEN ', State '     +CONVERT(varchar(30),   ERROR_STATE()      ) ELSE '' END
    --             +CASE WHEN ERROR_PROCEDURE()  IS NOT NULL THEN ', Procedure ' +                       ERROR_PROCEDURE()    ELSE '' END
    --             +CASE WHEN ERROR_LINE()       IS NOT NULL THEN ', Line '      +CONVERT(varchar(30),   ERROR_LINE()       ) ELSE '' END
    --             +CASE WHEN ERROR_MESSAGE()    IS NOT NULL THEN ', '           +                       ERROR_MESSAGE()      ELSE '' END

    --will echo back the complete original error message
    DECLARE @ErrorMessage nvarchar(4000), @ErrorNumber int, @ErrorSeverity int, @ErrorState int, @ErrorLine int
    SELECT @ErrorMessage = N'Error %d, Line %d, Message: '+ERROR_MESSAGE(),@ErrorNumber = ERROR_NUMBER(),@ErrorSeverity = ERROR_SEVERITY(),@ErrorState = ERROR_STATE(),@ErrorLine = ERROR_LINE()
    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorNumber,@ErrorLine)
    --RETURN 9999

END CATCH

输出:

Sending mail, TO: test@hotmail.com, SUBJECT: Reminder1, BODY: <b>test</b>
Sending mail, TO: test@hotmail.com, SUBJECT: Reminder2, BODY: hello