2010-06-18 4 views
4

Я рассматриваю единственный триггер SQL для обработки операций INSERT, UPDATE и DELETE как часть процесса аудита.Какой тип операции вызвал триггер в SQL Server 2008?

Есть ли какая-либо инструкция, функция или переменная @@, я могу опросить, чтобы узнать, какой тип операции запустил триггер?

Я видел следующий рисунок:

declare @type char(1) 
if exists (select * from inserted) 
    if exists (select * from deleted) 
     select @Type = 'U' 
    else 
     select @Type = 'I' 
else 
    select @Type = 'D' 

но есть что-нибудь еще немного более прямое или явное?

Thanks,
Neil.

ответ

1

Oracle имеет INSERTING, DELETING и UPDATING условные предикаты. В SQL Server нет эквивалента. (Хотя можно сделать IF UPDATE (column))

С MERGE заявление теперь можно делать все три в одной операции (Edit хотя кажется SQL Server будет divide it up into 3 operations)

1

У меня этот триггер аудита работает отлично для меня. Это требует таблицу аудиторскую проверку следующим образом:

CREATE TABLE [dbo].[Audit](
    [Type] [char](1) NULL, 
    [TableName] [varchar](128) NULL, 
    [PK] [varchar](1000) NULL, 
    [FieldName] [varchar](128) NULL, 
    [OldValue] [varchar](max) NULL, 
    [NewValue] [varchar](max) NULL, 
    [UpdateDate] [datetime] NULL, 
    [UserName] [varchar](128) NULL 
) ON [PRIMARY] 

GO 

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

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

Вам необходимо убедиться, что вы изменили имя таблицы в начале триггера.

CREATE TRIGGER [dbo].[TR_TableName_Audit] ON [dbo].[TableName] FOR INSERT, UPDATE, DELETE 

AS 


DECLARE @bit INT, 
     @field INT, 
     @maxfield INT, 
     @char INT, 
     @fieldname VARCHAR(128), 
     @TableName VARCHAR(128), 
     @PKCols VARCHAR(1000), 
     @sql VARCHAR(2000), 
     @UpdateDate VARCHAR(21), 
     @UserName VARCHAR(128), 
     @Type CHAR(1), 
     @PKSelect VARCHAR(1000)  

--You will need to change @TableName to match the table to be audited 


SELECT @TableName = 'TableName' 

-- date and user 

SELECT   @UserName = SYSTEM_USER ,  
       @UpdateDate = CONVERT(VARCHAR(8), GETDATE(), 112) 
       + ' ' + CONVERT(VARCHAR(12), GETDATE(), 114) 

-- Action 

IF EXISTS (SELECT * FROM inserted)  

     IF EXISTS (SELECT * FROM deleted)    

        SELECT @Type = 'U'  
     ELSE    
        SELECT @Type = 'I' 
ELSE  
     SELECT @Type = 'D' 

-- get list of columns 

SELECT * INTO #ins FROM inserted 
SELECT * INTO #del FROM deleted 

-- Get primary key columns for full outer join 

SELECT @PKCols = COALESCE(@PKCols + ' and', ' on')     
       + ' i.' + c.COLUMN_NAME + ' = d.' + c.COLUMN_NAME  

FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk ,    
     INFORMATION_SCHEMA.KEY_COLUMN_USAGE c  
WHERE pk.TABLE_NAME = @TableName  
AND  CONSTRAINT_TYPE = 'PRIMARY KEY'  
AND  c.TABLE_NAME = pk.TABLE_NAME  
AND  c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME 

-- Get primary key select for insert 

SELECT @PKSelect = COALESCE(@PKSelect+'+','')   
     + '''<' + COLUMN_NAME   
     + '=''+convert(varchar(100),coalesce(i.' + COLUMN_NAME +',d.' + COLUMN_NAME + '))+''>'''   

FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk ,    
     INFORMATION_SCHEMA.KEY_COLUMN_USAGE c  
WHERE pk.TABLE_NAME = @TableName  
AND  CONSTRAINT_TYPE = 'PRIMARY KEY'  
AND  c.TABLE_NAME = pk.TABLE_NAME  
AND  c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME 

IF @PKCols IS NULL 
    BEGIN  
      RAISERROR('no PK on table %s', 16, -1, @TableName)  
      RETURN 
    END 

SELECT   @field = 0,   
       @maxfield = MAX(ORDINAL_POSITION)   
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = @TableName 

    WHILE @field < @maxfield 

     BEGIN  

       SELECT @field = MIN(ORDINAL_POSITION)     
       FROM INFORMATION_SCHEMA.COLUMNS     
       WHERE TABLE_NAME = @TableName     
       AND ORDINAL_POSITION > @field  

       SELECT @bit = (@field - 1)% 8 + 1  
       SELECT @bit = POWER(2,@bit - 1)  
       SELECT @char = ((@field - 1)/8) + 1  

       IF SUBSTRING(COLUMNS_UPDATED(),@char, 1) & @bit > 0 
             OR @Type IN ('I','D')  

       BEGIN    

         SELECT @fieldname = COLUMN_NAME       
         FROM INFORMATION_SCHEMA.COLUMNS       
         WHERE TABLE_NAME = @TableName       
         AND ORDINAL_POSITION = @field    


         SELECT @sql = ' 
         insert Audit (Type, TableName, PK, FieldName, OldValue, NewValue, UpdateDate, UserName) 

         select ''' + @Type + ''','''   
           + @TableName + ''',' + @PKSelect  
           + ',''' + @fieldname + ''''  
           + ',convert(varchar(max),d.' + @fieldname + ')'  
           + ',convert(varchar(max),i.' + @fieldname + ')'  
           + ',''' + @UpdateDate + ''''  
           + ',''' + @UserName + ''''  
           + ' from #ins i full outer join #del d'  
           + @PKCols  + ' where i.' + @fieldname + ' <> d.' + @fieldname 
           + ' or (i.' + @fieldname + ' is null and d.' 
                      + @fieldname 
                      + ' is not null)'   
           + ' or (i.' + @fieldname + ' is not null and d.' 
                 + @fieldname  
                      + ' is null)' 

           EXEC (@sql)  

       END 
     END 
+1

Это было бы блог Джона Галлоуэй тогда! http://weblogs.asp.net/jgalloway/archive/2008/01/27/adding-simple-trigger-based-auditing-to-your-sql-server-database.aspx –

+0

@Neil Moss - Ах почти - именно в блоге Найджела Риветта я впервые встретил его. Оригинальная статья связана через блог Джона Галлоуэя. Благодарю. – codingbadger

+0

Спасибо @Barry - я хотел знать, можно ли сделать INSERT, UPDATE или DELETE короче, чем в этом скрипте? –

Смежные вопросы