Как получить триггер для каждой вставленной строки во время INSERT INTO Table (и т.д.) SELECT * FROM Table2? - PullRequest
4 голосов
/ 27 апреля 2011

Я пытался избегать использования курсора в этом конкретном случае только потому, что мне не нравятся компромиссы, и именно так происходит, процесс, который я использую, делает триггеры в любом случае похожими на правильный курс действий.

Хранимая процедура вставляет запись, основанную на сложном сочетании предложений, используя триггер вставки, я отправляю электронное письмо целевому пользователю, в котором ему предлагается посетить сайт.Это просто и отлично работает.

Однако другая процедура - запускать каждую ночь и распространять все не просмотренные записи.Я делал это, вставляя еще одну вставку на основе поля выбора даты, с которого оно было назначено.То есть:

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

Ответы [ 2 ]

10 голосов
/ 27 апреля 2011

Триггер вставки вызывается один раз для массовых вставок, но в триггере вы можете использовать специальную таблицу 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

Я не тестировал, нодолжно работать

4 голосов
/ 27 апреля 2011

Если вы отправляете электронное письмо, я бы не стал делать это из триггера.Вы действительно хотите, чтобы люди не могли вставлять записи, потому что сервер электронной почты не работает?

Обычно лучше вставлять записи в таблицу из триггера, а затем иметь задание, которое отправляет электронные письма, которые запускаютсякаждую минуту или около того и обновляет статус электронной почты для отправки и добавляет дату и время отправки в таблицу при отправке каждой записи.Это не только позволяет вставлять записи, когда электронные письма не работают, но и перемещает цикл для отправки каждого отдельного письма в таблицу, к которой у пользователей нет доступа (и, таким образом, любая задержка обработки многих записей будет влиять только на новых пользователей, а не на кого-либо еще), и этопозволяет просматривать историю отправленных писем, что помогает, когда люди спрашивают, почему они не получили его.Вы также можете записать в таблицу, если электронное письмо не удалось отправить, чтобы помочь определить неверные адреса электронной почты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...