2014-12-09 4 views
1

Im пытается заставить этот триггер работать при попытке удалить запись. То, как это работает, заключается в том, что когда кто-то пытается удалить запись, она откатывается и вставляет запись аудита в таблицу TbAudit, которая, кстати, у всех столбцов есть ограничение NOT NULL. Однако выясняется, что это не будет сделано, потому что по какой-то причине я не понимаю, когда я пытаюсь удалить запись, он отобразит сообщение и откат, но все мои переменные в выражении select получают значения NULL, хотя Im вытаскивает их непосредственно из «удаленная» таблица. Пожалуйста помоги.SQL After Delete Trigger имеет значения Null в удаляемом псевдонимах?

USE BdPlan 
GO 
CREATE TRIGGER TrAudit 
    ON Plan.TPlan 
    AFTER DELETE 
AS 
BEGIN 
DECLARE @IdPlan = int, 
     @IdEmployee int, 
     @Month int, 
     @Year int 

ROLLBACK 
PRINT 'CANT DELETE RECORDS' 

-- All variables are getting NULL 

SELECT @IdPlan = D.IdPlan,    
     @IdEmployee = D.IdEmployee , 
     @Month = D.Month,    
     @Year = D.Year     

FROM deleted AS D 

INSERT INTO BdAudit.dbo.TbAudit 
      VALUES 
       (
       @IdPlan, 
       @IdEmployee, 
       @Month, 
       @Year, 
       SUSER_NAME(), 
       GETDATE() 
       ) 
END 

ответ

0

Я считаю, что могут быть проблемы с этим подходом:

  • вы пытаетесь получить доступ к DELETED pseudotable после того, как сделка была откат - он будет иметь нулевые строки после отката (см)
  • триггер только пытается иметь дело с одним удалением строки - он должен быть в состоянии обрабатывать многорядные удаляет

он также не что вставка непосредственно в таблицу аудита из псевдонима «Удалено» до ROLLBACK, конечно, также вернет данные аудита.

From here это очевидно, можно кэшировать данные для аудита в переменной в @Temporary таблицы, а затем сделать ROLLBACK (что не отменяет таблицу @Temp), а затем сделать вставку аудита:

ALTER trigger d_foo ON FOO AFTER DELETE 
AS BEGIN 
    DECLARE @Temp AS TABLE 
    (
     ID INT, 
     -- Obviously add all your fields go here 
    ); 

    INSERT INTO @Temp(ID) 
     SELECT ID FROM DELETED; 

    ROLLBACK TRAN; 

    insert into fooaudit(id) 
     select id from @Temp; 
END; 

Simplified SqlFiddle here с удалением нескольких строк.

Для подтверждения, псевдоним DELETED содержит нулевые строки после ROLLBACK в триггере, как это modified Fiddle demonstrates.

+1

Абсолютный гений, большое спасибо. Это сделал трюк! – jebc88

+1

Будьте осторожны с использованием ROLLBACK внутри триггера. Если ваш внешний код имеет явную транзакцию, вы получите исключение, потому что не будет транзакции для отката или фиксации. Я бы предпочел использовать RAISERROR, чтобы вызывающее приложение узнало, что что-то произошло, и вы не получаете несогласованных транзакций. –