How can I get a trigger to fire on each inserted row during an INSERT INTO Table (etc) SELECT * FROM Table2?

后端 未结 2 1223
陌清茗
陌清茗 2020-12-02 00:44

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

相关标签:
2条回答
  • 2020-12-02 01:04

    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.

    0 讨论(0)
  • 2020-12-02 01:13

    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
    

    I didn't tested, but should work

    0 讨论(0)
提交回复
热议问题