【问题标题】:Multiple table SQL trigger an email to update多表 SQL 触发邮件更新
【发布时间】:2017-03-21 18:39:12
【问题描述】:

好的,这里肯定更近了,但现在它会在一次记录更新中发送大量电子邮件?我知道我在这里遗漏了一些东西。第一次射击光标,所以我猜我在那里做错了什么?一如既往,感谢您的帮助!!

create trigger eMailScheduleChange on dbo.BOOKINGS after update as

set nocount on;

Declare EmailCursor Cursor read_only for
    select r.Name as RName
    , c.Name as CName
    , i.BookingTypeId
    , i.Start
    , i.Finish
    , r.Email
from Wallchart.dbo.BOOKINGS b
inner join Wallchart.dbo.CUSTOMERS c on b.CustomerId = c.CustomerId
inner join Wallchart.dbo.RESOURCES r on b.ResourceId = r.ResourceId
inner join Inserted i on i.CustomerId = b.CustomerId
where i.BookingTypeId <> b.BookingTypeId 

Declare @Email as varchar(50)
Declare @CName as varchar(100)
Declare @Start as datetime
Declare @RName as varchar (100)
Declare @Finish as datetime
Declare @body as varchar (255)
Declare @BookingTypeId as varchar (50)

open EmailCursor
Fetch next from EmailCursor
INTO @Email, @CName, @Start, @RName, @Finish, @BookingTypeId
While @@FETCH_STATUS=0

BEGIN

    Set @body = '<Account cancelled>' + @CName + @Start + @Finish

EXEC msdb.dbo.sp_send_dbmail

@profile_name = 'SQLMail',
@recipients = @Email,
  @subject = 'Account Update',
  @body = @body

FETCH NEXT FROM EmailCursor INTO @Email, @CName, @Start, @RName, @Finish,       @BookingTypeId
SET NOCOUNT OFF
END
Close EmailCursor
Deallocate EmailCursor

【问题讨论】:

  • 您应该做的第一件事是停止在任何地方使用 "。这会使阅读变得更加困难,并且实际上可能会导致问题。此外,如果您要使用表别名,您实际上应该提供不同的名称或者提供别名是没有意义的。这就像说你的名字是 Travis(又名 Travis)。
  • 现在...您的实际问题是什么?在我看来,如果您需要在 BookingTypeID 更改时发送电子邮件,您将在 BOKINGS 上创建触发器。这似乎是保存 BookingTypeID 的表。
  • 我明白,那里有奇怪的习惯力量。正确,当 BookTypeId 更改时,它在 bookings 表中更改。但是,客户名称在客户表中,资源名称和电子邮件在资源表中。使用触发器,我可以向自己发送一封电子邮件并说它已更改,但我不知道客户名称、资源是谁等。因此,如果预订类型 ID 已更改,请通过电子邮件发送资源电子邮件、客户名称和预订开始。
  • 那么触发器在逻辑上只能属于BOOKINGS表吧?您希望它触发的时间是值更改的时间。您希望触发器发送电子邮件吗?为什么不能简单地将这个查询放在触发器中以检索您需要的值?没有规定触发器内的代码只能引用自身。

标签: sql sql-server triggers sql-server-2008-r2 automation


【解决方案1】:

我想你可能有这样的印象,触发器中的查询不允许从另一个表中读取数据。情况并非如此,否则触发器将毫无用处。这是您的触发器的外观的存根。我演示了如何提取你想要的信息。从那里它只是调用 sp_send_dbmail。

create trigger MyTrigger on dbo.BOOKINGS for update as
    set nocount on;

    select r.Name
        , c.Name
        , i.BookingTypeId
        , i.Start
        , i.Finish
        , r.Email
    from Schedule.dbo.BOOKINGS b
    inner join Wallchart.dbo.CUSTOMERS c on b.CustomerId = c.CustomerId
    inner join Schedule.dbo.RESOURCES r on b.ResourceId = r.ResourceId
    inner join Inserted i on i.SomeKeyValue = b.SomeKeyValue
    where i.BookingTypeID <> b.BookingTypeID

    --Now you can see how to capture all the information. All that is left is to call sp_send_dbmail
    --https://msdn.microsoft.com/en-us/library/ms190307.aspx

【讨论】:

  • 谢谢肖恩,这就是我之前结束的地方。我不必设置变量才能传递给 sp_send_dbmail 吗? ie 'Declare ATempEmail as varchar(50) 'Set ATempEmail = ?
  • 是的,您需要将这些值放入变量中。发送电子邮件是非常罕见的情况之一,其中光标实际上是最佳选择。
【解决方案2】:

SQL Server 不支持从脚本直接邮寄。但你还有其他选择。

首先创建一个表来捕获正在更改的记录,并设置一个 EmailFlag 以便您可以确定您是否已通知该用户有关更改。

创建一个存储过程,它将为您提供所有已经历一些更改但未通过电子邮件通知的用户的列表(EmailFlag =“N”或类似的东西)

现在使用 SSIS 创建一个发送邮件任务,为所有这些用户发送详细信息电子邮件。

一旦您为每个用户发送了电子邮件,您就可以将该记录的 EmailFlag 更新为“Y”。您可以将 SSIS 包设置为 SQL Server 中的计划作业,使其在一定的时间间隔内自动运行。

您可以在 SSIS 中使用 for each 循环容器,以便您可以单独向每个收件人发送邮件

请参考以下链接了解更多详情 SSIS - How to configure a send mail task

【讨论】:

  • SSIS 在这里有点矫枉过正。
  • 尤其是当您可以致电sp_send_dbmail
  • 但我认为这里更好,因为您可以直接访问 SQL 数据库,并且与其他语言或工具相比,它可以让您更好地控制数据库
  • 这就像用艾布拉姆斯坦克杀死一只蚊子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-09
  • 2018-05-24
  • 2012-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多