如何在 INSERT INTO Table(等)SELECT * FROM Table2 期间触发每个插入行的触发器?

发布于 2024-11-04 03:14:10 字数 1057 浏览 2 评论 0原文

我一直试图避免在这种特殊情况下使用游标,只是因为我不喜欢这种权衡,而我正在使用的过程恰好使触发器看起来像是正确的操作过程。

存储过程根据复杂的子句组合插入一条记录,使用插入触发器,我向目标用户发送电子邮件,告诉他们访问某个网站。这很简单并且效果很好。

然而,另一个过程是每晚运行并重新分发所有未查看的记录。我这样做的方法是根据分配日期字段上的选择进行另一次插入。也就是说:

INSERT INTO Table (ID, User, AssignDate, LastActionDate)
    SELECT 
        ID
        ,User
        ,GETDATE() [AssignDate]
        ,GETDATE() [LastModifiedDate]
    FROM Table2
        /*snip*/

触发器适用于单个插入,但上面的 select 语句仅适用于最后插入的行。有没有办法绕过这种行为?它毁了整个事情!

编辑(触发代码):

ALTER TRIGGER dbo.Notify
    ON  dbo.Table
    AFTER INSERT
AS 
BEGIN

    DECLARE @EmailSender varchar(50)='Sender Profile'
    DECLARE @Identity int
    DECLARE @User varchar(20)
    DECLARE @Subject varchar(50)

    SET @Identity=@@Identity

    SELECT @User=User, @Subject='(' + CONVERT(varchar,@Identity) + ')!'
    FROM Table
    WHERE
        idNum=@Identity

    exec msdb.dbo.sp_send_dbmail
        @profile_name=@EmailSender,
        @recipients=@User
        @subject=@Subject,
        @body='//etc'

END

I've been trying to avoid using a cursor in this particular case just because I dislike the tradeoffs, and it just so happens a process I'm using makes triggers look like the proper course of action anyway.

A stored procedure inserts a record based off of a complicated mix of clauses, using an insert trigger I send an email to the target user telling them to visit a site. This is easy and works fine.

However, another procedure is to run nightly and redistribute all unviewed records. The way I was doing this was to do another insert based on a select on a date field from when it was assigned. To wit:

INSERT INTO Table (ID, User, AssignDate, LastActionDate)
    SELECT 
        ID
        ,User
        ,GETDATE() [AssignDate]
        ,GETDATE() [LastModifiedDate]
    FROM Table2
        /*snip*/

The trigger works on individual inserts, but the select statement above only works on the last inserted row. Is there a way to get around this behavior? It ruins the whole thing!

Edit (trigger code):

ALTER TRIGGER dbo.Notify
    ON  dbo.Table
    AFTER INSERT
AS 
BEGIN

    DECLARE @EmailSender varchar(50)='Sender Profile'
    DECLARE @Identity int
    DECLARE @User varchar(20)
    DECLARE @Subject varchar(50)

    SET @Identity=@@Identity

    SELECT @User=User, @Subject='(' + CONVERT(varchar,@Identity) + ')!'
    FROM Table
    WHERE
        idNum=@Identity

    exec msdb.dbo.sp_send_dbmail
        @profile_name=@EmailSender,
        @recipients=@User
        @subject=@Subject,
        @body='//etc'

END

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风和你 2024-11-11 03:14:10

对于批量插入,插入触发器会被调用一次,但在触发器上,您可以使用特殊的 inserted 表来获取所有插入的行。

因此,假设您有一个像这样的插入触发器,它记录插入到 table 中的所有行。

create trigger trgInsertTable 
on dbo.table
for insert
as
   insert tableLog(name)
    select name from inserted

使用此触发器,当您在 table 上进行批量插入时,>tableLog 填充的行数与插入到 table 中的行数相同。

对于您的特定触发器,由于您需要为每一行调用存储过程,因此需要使用游标:

ALTER TRIGGER dbo.Notify
    ON  dbo.Table
    AFTER INSERT
AS 
BEGIN

    DECLARE @EmailSender varchar(50)='Sender Profile'
    DECLARE @User varchar(20)
    DECLARE @Subject varchar(50)

    DECLARE cursor CURSOR FOR
      SELECT User, '(' + CONVERT(varchar, Id) + ')!'
        FROM inserted
    
    OPEN cursor
    FETCH NEXT FROM cursor INTO @User, @Subject
    WHILE @@FETCH_STATUS = 0
    BEGIN
      exec msdb.dbo.sp_send_dbmail
          @profile_name=@EmailSender,
          @recipients=@User
          @subject=@Subject,
          @body='//etc'
      FETCH NEXT FROM cursor INTO @User, @Subject
    END
    CLOSE cursor
    DEALLOCATE cursor

END

The insert trigger is called once for bulk inserts, but on the trigger you can use the special inserted table to get all the inserted rows.

So, imagine you have an insert trigger like this one, that logs all the rows inserted into table

create trigger trgInsertTable 
on dbo.table
for insert
as
   insert tableLog(name)
    select name from inserted

With this trigger, when you make a bulk insert on table, the tableLog is filled with the same number of rows that were inserted to table

For you specific trigger, since you need to call a stored procedure for each row, you need to use a cursor:

ALTER TRIGGER dbo.Notify
    ON  dbo.Table
    AFTER INSERT
AS 
BEGIN

    DECLARE @EmailSender varchar(50)='Sender Profile'
    DECLARE @User varchar(20)
    DECLARE @Subject varchar(50)

    DECLARE cursor CURSOR FOR
      SELECT User, '(' + CONVERT(varchar, Id) + ')!'
        FROM inserted
    
    OPEN cursor
    FETCH NEXT FROM cursor INTO @User, @Subject
    WHILE @@FETCH_STATUS = 0
    BEGIN
      exec msdb.dbo.sp_send_dbmail
          @profile_name=@EmailSender,
          @recipients=@User
          @subject=@Subject,
          @body='//etc'
      FETCH NEXT FROM cursor INTO @User, @Subject
    END
    CLOSE cursor
    DEALLOCATE cursor

END
与他有关 2024-11-11 03:14:10

如果您要发送电子邮件,我不会通过触发器来发送电子邮件。您真的希望人们因为电子邮件服务器关闭而无法插入记录吗?

通常最好将记录从触发器插入到表中,然后有一个作业发送每分钟左右运行的电子邮件,并将电子邮件状态更新为已发送,并在发送每条记录时将发送的日期时间添加到表中。这不仅允许您在电子邮件关闭时插入记录,还可以移动循环以将每封单独的电子邮件发送到用户未访问的表(因此处理许多记录的任何延迟只会影响新用户,而不影响其他任何人)允许您查看发送电子邮件的历史记录,当人们质疑为什么没有收到电子邮件时,这会有所帮助。您还可以在表格中记录电子邮件发送失败的情况,以帮助识别错误的电子邮件地址。

If you are sending an email, I would not do that from a trigger. Do you really want people to not be able to insert records because the email server is down?

It is usually better to insert the records to a table from the trigger and then have a job that sends the emails that runs every minute or so and updates the email status to sent and adds the sent datetime to the table when each record is sent. This not only allows you to insert records when emails are down, it moves the looping to send each individual email to a table the users are not accessing (and thus any delay processing many records will only affect the new users not anyone else) and it allows you to see a history of when you sent the email which helps when people question why they didn't get it. You can also record in the table if the email failed to send to help identify bad email addresses.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文