使用触发器中的游标更改db_sendmail的主题

时间:2015-05-18 17:35:36

标签: sql-server triggers cursor sp-send-dbmail

SQl Server 2008 R2 - 我设置了一个触发器,用于将电子邮件发送到由第三方系统监控的特定电子邮件地址,该系统根据该邮件的主题向某些人群发送邮件。对此的限制是每个消息只能在主题中有一个组号。但是我需要从触发器向至少两个组发送相同的消息,这意味着必须使用两个不同的主题行生成两个单独的电子邮件。我想可能触发器中的光标会完成这个但我不确定如何写它。 所以在下面的代码中我有@cat,我需要在触发器启动时发送主题为“ED”的电子邮件。然后,我需要发送另一封电子邮件,其中主题是根据当前用于设置主题行的案例陈述的条件设置的。我已经更新了代码如下并删除了标量变量已经移动到基于集合的触发器(??)我也创建并将信息插入到“电子邮件”表中,该表将设置为每个运行一个服务10秒并通过电子邮件发送设置为0的所有记录,然后将标志更新为1.

新守则 -

CREATE TABLE [dbo].[tb_BatchEmail] (
    [BatchEmailID] [bit] NOT NULL DEFAULT 0
    ,[To] [varchar](50) NOT NULL DEFAULT 'someemail' --will never change
    ,[Body] [varchar](255) NULL
    ,[Subject] [varchar](20) NOT NULL
    ,[Profile] [varchar](50) NOT NULL DEFAULT 'Alert' --will never change
    ,[OrderID] [varchar] (25) NULL
    ,[OrderDateTime] [datetime] NULL
    ,[SentDateTime] [datetime] NULL
    ,CONSTRAINT msg_pk PRIMARY KEY CLUSTERED (BatchEmailID)
    ) ON [PRIMARY]
GO



  ALTER TRIGGER [dbo].[VeOrders] ON [dbo].[Orders]
        FOR INSERT
        AS
            SELECT @visitid = i.VisitID
    ,@priority = Priority
    ,@cat = Category
    ,@procedure = OrderedProcedureName
    ,@orderid = OrderID
    ,@orderdate = OrderDateTime
    ,@locationid = CurrentLocationID
    ,@roomid = CASE 
        WHEN RoomTreatmentID IS NULL
            THEN 'No Room#'
        ELSE RoomTreatmentID
        END
FROM inserted i
INNER JOIN livedb.dbo.EdmPatients edp
    ON edp.VisitID = i.VisitID
WHERE Priority = 'STAT'
    AND Category IN ('CT', 'MRI', 'XRAY', 'US', 'NUC', 'ECHO')
    AND CurrentLocationID = 'ED'

IF @cat IN ('CT', 'MRI', 'XRAY', 'US', 'NUC', 'ECHO')
    AND @priority = 'STAT'
    AND @locationid = 'ED'
BEGIN
    DECLARE @msg VARCHAR(500)
    DECLARE @subject VARCHAR(500)

    SET @msg = @roomid + '-' + @procedure + '-' + @priority + '.' --+ 'Order DateTime/Number ' + @order + '/+ @locationid + ' '  + @orderid
    SET @subject = CASE 
            WHEN @cat = 'US'
                THEN 'Test Ultra Sound'
            WHEN @cat = 'CT'
                THEN 'Test C T'
            WHEN @cat = 'XRAY'
                THEN 'Test X-Ray'
            END

    INSERT INTO livedb.dbo.tb_BatchEmail (
        Body
        ,[Subject]
        ,OrderID
        ,OrderDateTime
        )
    SELECT Body = @msg
        ,[Subject] = @subject
        ,OrderID = @orderid
        ,OrderDateTime = @orderdate

END

旧代码 -

ALTER TRIGGER [dbo].[VeOrders] ON [dbo].[Orders]
FOR INSERT
AS
IF NOT EXISTS (
        SELECT *
        FROM dbo.EdmPatients
        WHERE CurrentLocationID = 'ED'
        )
    RETURN

DECLARE @priority VARCHAR(50)
DECLARE @cat VARCHAR(50)
DECLARE @procedure VARCHAR(50)
DECLARE @orderid VARCHAR(50)
DECLARE @locationid VARCHAR(10)
DECLARE @roomid VARCHAR(10)
DECLARE @visitid VARCHAR(50)

SELECT @visitid = VisitID
    ,@priority = Priority
    ,@cat = Category
    ,@procedure = OrderedProcedureName
    ,@orderid = OrderID
    ,@locationid = CurrentLocationID
    ,@roomid = CASE 
        WHEN RoomTreatmentID IS NULL
            THEN 'No Room#'
        ELSE RoomTreatmentID
        END
FROM inserted i
INNER JOIN dbo.EdmPatients edp
    ON edp.VisitID = i.VisitID
WHERE Priority = 'STAT'
    AND Category IN ('CT', 'MRI', 'XRAY', 'US', 'NUC', 'ECHO')
    AND CurrentLocationID = 'ED'

IF @cat IN ('CT', 'MRI', 'XRAY', 'US', 'NUC', 'ECHO')
    AND @priority = 'STAT'
    AND @locationid = 'ED'
BEGIN
    DECLARE @msg VARCHAR(500)
    DECLARE @subject VARCHAR(500)

    SET @msg = @roomid + '-' + @procedure + '-' + @priority + '.' 
    SET @subject = CASE
            WHEN @cat = 'CT'
                THEN '55194'
            WHEN @cat = 'US'
                THEN '59843'
            WHEN @cat = 'XRAY'
                THEN '70071'
            END

    EXEC msdb.dbo.sp_send_dbmail 
         @recipients = N'someemail'
        ,@body = @msg
        ,@subject = @subject
        ,@profile_name = 'Alerts'
END

1 个答案:

答案 0 :(得分:0)

我会将创建电子邮件和发送邮件的问题分开。有一项服务,其唯一的工作是发送电子邮件。电子邮件是抽象的,因为它们都有一个From,一个To,一个Body和一个Subject。创建一个包含所有这些字段的表(例如名为BatchEmail)。

然后你的触发器很简单。它只是在普通的select语句中插入BatchEmail表。

insert into BatchEmail
(To, Body, Subject, Profile)
select N'someemail',
       @msg,
       CASE
            WHEN @cat = 'CT'
                THEN '55194'
            WHEN @cat = 'US'
                THEN '59843'
            WHEN @cat = 'XRAY'
                THEN '70071'
            END,
        'Alerts'

您的BatchEmail表应该有一些列或标志,指示何时或是否已发送。

您的服务(甚至是桌面上的插入触发器,如果​​您真的喜欢触发器)可以在未经处理的情况下选择1行。

while true
begin

    select top 1 
           @BatchEmailID = batchEmailID,
           @To = to,
           @From = from,
           @Body = body,
           @Subject = subject,
           @ProfileName = ProfileName
    from BatchEmail
    where processed = 0

    if(@BatchEmailID is null)
    break;

    exec msdb.dbo.sp_send_dbmail @To, @Body, @Subject, @ProfileName

    update BatchEmail
    set processed = 1
    where BatchEmailID = @BatchEmailID

end

如果您仍然不想拥有单独的服务并坚持在触发器中执行所有这些操作,您可以将@BatchEmail转换为表变量,仍然使用@Processed位列并一次选择1行,更新@Processed在每一行之后。