2014-09-22 4 views
0

У меня должен быть один триггер, который запускается либо в операциях UPDATE, либо DELETE. У меня триггер работает нормально, когда обновляется один определенный столбец. Однако мне нужна другая логика, когда была запущена операция DELETE. Как бы у меня была логика внутри одного триггера? Вот то, что я до сих пор:SQL-триггер при обновлении или удалении

ALTER TRIGGER [dbo].[Audit_Emp_Trigger] 
    ON [dbo].[EMPLOYEE] 
    AFTER UPDATE, DELETE 
AS 

BEGIN 
    --Only execute the trigger if the Dno field was updated or deleted 
    IF UPDATE(Dno) 
    BEGIN 

    --If the Audit_Emp_Record table does not exist already, we need to create it 
    IF OBJECT_ID('dbo.Audit_Emp_Record') IS NULL 
    BEGIN 
    --Table does not exist in database, so create table 
    CREATE TABLE Audit_Emp_Record 
    (
    date_of_change smalldatetime, 
    old_Lname varchar (50), 
    new_Lname varchar (50), 
    old_ssn int, 
    new_ssn int, 
    old_dno int, 
    new_dno int 
    ); 

    --Once table is created, insert the values of the update operation into the table 
    INSERT INTO Audit_Emp_Record(date_of_change, old_Lname, new_Lname, old_ssn, new_ssn, old_dno, new_dno) SELECT GETDATE(), D.Lname, I.Lname, D.Ssn, I.Ssn, D.Dno, I.Dno FROM inserted I JOIN deleted D ON I.Ssn = D.Ssn 

    END 

    ELSE 
    BEGIN 
    --The table already exists, so simply insert the new values of the update operation into the table 
    INSERT INTO Audit_Emp_Record(date_of_change, old_Lname, new_Lname, old_ssn, new_ssn, old_dno, new_dno) SELECT GETDATE(), D.Lname, I.Lname, D.Ssn, I.Ssn, D.Dno, I.Dno FROM inserted I JOIN deleted D ON I.Ssn = D.Ssn 
    END 

    END 

END 
+0

Если логика настолько различна между 'UPDATE' и' DELETE' - почему бы не просто иметь два отдельных триггера, каждый из которых фокусировался на одной операции? –

+0

@marc_s: комментарии, связанные с моим ответом, показали, что логика не была совсем иной. Обе операции записывают данные в ту же таблицу аудита; 'UPDATE' присоединяется к таблицам' INSERTED' и DELETED', а 'DELETE' просто тянет из таблицы' DELETED'. Просто FYI. –

ответ

2

Вы можете проверить тип операции, видя, какой из magic-/псевдо-таблиц - INSERTED и DELETED есть данные в них. Я предпочитаю использовать что-то вроде следующего:

DECLARE @Operation CHAR(1); 

IF (EXISTS(SELECT * FROM inserted)) 
BEGIN 

    IF (EXISTS(SELECT * FROM deleted)) 
    BEGIN 
     -- rows in both has to be an UPDATE 
     SET @Operation = 'U'; 
    END; 
    ELSE 
    BEGIN 
     -- no rows in "deleted" has to be an INSERT 
     SET @Operation = 'I'; 
    END; 

END; 
ELSE 
BEGIN 
    -- no rows in "inserted" has to be a DELETE 
    SET @Operation = 'D'; 
END; 

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

Что-то вроде:

IF (@Operation = 'U') 
BEGIN 

    --Only execute the trigger if the Dno field was updated or deleted 
    IF UPDATE(Dno) 
    BEGIN 
     {your current code here} 
    END; 
END; 
ELSE 
BEGIN 
    {what to do if the operation is a DELETE goes here} 
END; 

Технически вам не нужно ELSE условия, которое устанавливает @Operation = 'I';, но если вы собираетесь копировать/вставить этот код в различные триггера или держать вокруг как шаблон тогда нет вреда в нем обрабатываются все три условия.

Кроме того, только в качестве побочного отметить, что вам не нужно в ELSE состояние IF OBJECT_ID('dbo.Audit_Emp_Record') IS NULL заявления, ни INSERT INTO Audit_Emp_Record, который только после CREATE TABLE но перед END. Просто выполните CREATE TABLE, если он не существует, а затем выполните INSERT вне этого теста. Значение:

IF UPDATE(Dno) 
BEGIN 
    --If the Audit_Emp_Record table does not exist already, we need to create it 
    IF OBJECT_ID('dbo.Audit_Emp_Record') IS NULL 
    BEGIN 
     --Table does not exist in database, so create table 
     CREATE TABLE Audit_Emp_Record 
     ... 
    END 

    INSERT INTO Audit_Emp_Record(...) 
END 
+0

Я не мог сделать ELSE, потому что я хочу только выполнить блок кода в IF UPDATE (Dno), если обновлен столбец Dno, а не для каких-либо других столбцов. –

+0

@JonathanDurda: ah, good point. Думаю, я смогу удалить эту часть своего ответа. Это было что-то, что появилось у меня в голове. Но первая часть все еще стоит. –

+0

Благодарим за решение. Мой единственный вопрос: могу ли я определить, какой столбец был удален, сканируя удаленную таблицу? Например, я хочу только выполнить код внутри блока DELETE, если столбец Dno был удален. –