9

ユーザーテーブルに以下のようなトリガーがあり、列が更新された監査テーブルと以前の値に挿入されます。

ALTER TRIGGER [dbo].[trgAfterUpdate] ON [dbo].[tbl_User]
AFTER UPDATE
AS


    declare @fieldname varchar(128) ;
    declare @OldValue varchar(255);
    declare @CreateUser varchar(100) ;
    declare @User_Key int;

    select @CreateUser =i.user_name from deleted i; 
    SELECT @User_Key = i.user_key from inserted i;  

    if update(user_name)
      begin
          select @OldValue=j.user_name from deleted j;  
          set @fieldname = 'user_name';

            insert into tbl_Audit(user_key, field_name, previuos_Value, user_name)
            values(@User_Key ,@fieldname,@OldValue, @CreateUser);

      end

しかし、私の質問は、テーブルに 100 個のフィールドがあることです。if条件で100書けません。while ループを使用する方法と、パフォーマンスにどのように影響するかについての提案が必要です。

ありがとう

4

2 に答える 2

18

これを試してみてください -

ALTER TRIGGER [dbo].[trgAfterUpdate] 

    ON [dbo].[tbl_User]
    AFTER UPDATE

AS BEGIN

    SET NOCOUNT ON
    SET XACT_ABORT ON

    DECLARE @DocumentUID UNIQUEIDENTIFIER

    DECLARE cur CURSOR FORWARD_ONLY READ_ONLY LOCAL FOR
        SELECT DocumentUID, ...
        FROM INSERTED

    OPEN cur

    FETCH NEXT FROM cur INTO @DocumentUID, ...

    WHILE @@FETCH_STATUS = 0 BEGIN

        DECLARE 
              @BeforeChange XML 
            , @AfterChange XML

        SELECT @BeforeChange = (
            SELECT *
            FROM DELETED
            WHERE [DocumentUID] = @DocumentUID
            FOR XML RAW, ROOT
        )
        , @AfterChange = (
            SELECT *
            FROM INSERTED
            WHERE [DocumentUID] = @DocumentUID
            FOR XML RAW, ROOT
        )

        INSERT INTO dbo.LogUser (DocumentUID, BeforeChange, AfterChange)
        SELECT @DocumentUID, @BeforeChange, @AfterChange

        -- your business logic 

        FETCH NEXT FROM cur INTO @DocumentUID, ...

    END

    CLOSE cur
    DEALLOCATE cur

END
于 2013-06-12T07:07:50.080 に答える
-1

これと同様のクエリを使用してみてください。指定されたテーブルのすべての列に対して If ステートメントが生成されます。

注: これは完全にはテストされておらず、おそらくさらに調整が必要ですが、その背後にある考え方がわかります。

select 'if update(' + C.name + ')
  begin
      select @OldValue=j.' + C.name + ' from deleted j;  
      set @fieldname = ''' + C.name + ''';

        insert into tbl_Audit(user_key, field_name, previuos_Value, user_name)
        values(@User_Key ,@fieldname,@OldValue, @CreateUser);
  end'
from sys.all_columns C
inner join sys.tables T on C.object_id = T.object_id
where T.name = 'table_name' and T.schema_id = SCHEMA_ID('schema_name')

おそらくパフォーマンスの問題を引き起こす可能性があるため、 while ループを使用しない場合...

于 2013-06-12T10:54:07.910 に答える