2

SQL Server 2008 を初めて使用するので、皆さんからのアドバイスが必要です。inserted現在、古い値と新しい値を保持するために監査証跡を行っているため、deletedテーブルの SQL Server 2008 の変更された値を見つけたいと考えています。すべての列をループして、削除および挿入されたテーブルからどのフィールドの値が変化したかを調べるにはどうすればよいですか? if else ステートメントを比較してみました

例えば:

create trigger trg_XXX on dbo.table
after update
as
begin
    declare 
       @oldID varchar(6),
       @newID varchar(6)

    select @oldID = ID from deleted
    select @newID = ID from inserted

    if(@oldID != @newID)
       insert into table (a, b) values (@oldID, @newID)
    else
       print('do nothing')

カーソルを使用して、削除および挿入されたテーブルまたは別の方法をループする方法はありますか? 例を教えてください。

4

4 に答える 4

5

あなたの目標が何であるかはよくわかりませんが、このようなものかもしれないと思います。次のようなテーブルがあるとします。

CREATE TABLE Product
(
     ID      INT                   PRIMARY KEY,
     Name    NVARCHAR(100)         NOT NULL,
     Price   DECIMAL(10,2)         NOT NULL
);

そして、次のような監査テーブル:

CREATE TABLE ProductAudit
(
     AuditID      INT                   IDENTITY PRIMARY KEY, 
     ProductID    INT                   NOT NULL
     OldName      NVARCHAR(100)         NULL,
     OldPrice     DECIMAL(10,2)         NULL,
     NewName      NVARCHAR(100)         NULL,
     NewPrice     DECIMAL(10,2)         NULL
);

次に、トリガーを作成します。

CREATE TRIGGER TR_AUDIT
ON Product
FOR INSERT, UPDATE, DELETE
AS
BEGIN
       INSERT INTO ProductAudit (ProductID, OldName, OldPrice, NewName, NewPrice)
       SELECT 
           COALESCE(I.ID, D.ID),
           D.Name,
           D.Price,
           I.Name,
           I.Price
       FROM 
           INSERTED I FULL OUTER JOIN DELETED D ON I.ID = D.ID;
END
GO

そこにあります。

于 2014-04-25T07:44:11.203 に答える
2

magic tablesSQLサーバーで非公式に呼び出されたものを探していると思います。

テーブル " INSERTED" と " DELETED" は SQL Server のマジック テーブルと呼ばれます。これらのテーブルはデータベースに表示されません。TRIGGERしかし、" "からこれらのテーブルにアクセスできます。

レコードをテーブルに挿入すると、マジック テーブル " INSERTED" が作成されます。そのテーブルでは、現在挿入されている行が使用可能になります。このレコードは " TRIGGER" でアクセスできます。

トリガーが作成されたテーブルのレコードを更新すると、マジック テーブル " INSERTED" と " DELETED" の両方が作成され、更新されたレコードの古いデータは "DELETED" テーブルで利用可能になり、新しいデータはで利用可能になります。 「INSERTED」テーブル、トリガー内でアクセス中。

テーブルからレコードを削除すると、マジック テーブル " DELETED" が作成されます。そのテーブルでは、現在削除されている行が利用可能になります。このレコードは " TRIGGER" でアクセスできます。

例:

次のコードは、マジック テーブル " INSERTED"を説明しています。

CREATE TRIGGER LogMessage
ON EMP
FOR INSERT
AS
   DECLARE @EMPNAME varchar(50)
   SELECT @EMPNAME= (SELECT EMPNAME FROM INSERTED)
   INSERT INTO LOGTABLE(UserId,Message) values (@EMPNAME,'Record Added')
GO

次のコードはマジックテーブル " DELETED"を説明します

CREATE TRIGGER LogMessage
ON EMP
FOR DELETE
AS
   DECLARE @EMPNAME varchar(50)
   SELECT @EMPNAME= (SELECT EMPNAME FROM DELETED)
   INSERT INTO LOGTABLE(UserId,Message) values (@EMPNAME,'Record Removed')
GO

出典(これらの記事と著者のすべての功績):

http://www.codeproject.com/Questions/285423/what-is-magic-table-different-types-of-magic-table http://www.dotnetspider.com/resources/29332-Magic-tables-SQL -Server.aspx

. .

あるいは

、試すことができます: 変更追跡関数を使用して変更を取得する、組み込み関数を使用して変更を追跡する方法を説明する MSDN リンク。

CHANGETABLE(CHANGES …)関数

この行セット関数は、変更情報のクエリに使用されます。この関数は、内部の変更追跡テーブルに格納されているデータをクエリします。この関数は、変更された行の主キーと、操作、更新された列、行のバージョンなどの他の変更情報を含む結果セットを返します。

CHANGE_TRACKING_CURRENT_VERSION()関数

次回の変更のクエリ時に使用される現在のバージョンを取得するために使用されます。このバージョンは、最後にコミットされたトランザクションのバージョンを表します。

CHANGE_TRACKING_MIN_VALID_VERSION()関数

クライアントが持つことができる最小の有効なバージョンを取得し、CHANGETABLE() から有効な結果を取得するために使用されます。クライアントは、この関数によって返される値に対して最後の同期バージョンをチェックする必要があります。最後の同期バージョンがこの関数によって返されたバージョンよりも小さい場合、クライアントは CHANGETABLE() から有効な結果を取得できず、再初期化する必要があります。

http://technet.microsoft.com/en-us/library/cc280358%28v=sql.105%29.aspxで構文と使用法を参照してください。

それが役に立てば幸い。

于 2014-04-25T07:29:48.913 に答える
1

最初に: トリガー内でカーソルを使用しないでください - 絶対に!

2 番目: update ステートメントに含まれていたフィールドを特定するには、 UPDATE()またはCOLUMNS_UPDATED()を使用できます。

注: これは、値が変更されたフィールドをリストするのではなく、UPDATE ステートメントの SET 部分に含まれる列のリストのみを示します。

3番目:テーブルへの変更を監査するために使用できるさまざまな方法があります( SQLを使用している場合、MS SQL Serverで列の変更を検出する最も効率的な方法に関する受け入れられた回答には、使用方法に関する適切なリストとガイドラインがありますServer Enterprise は、Change Data Captureを使用して調べることもできます

私が使用するいくつかの監査コードの例 (列監査テーブルごとに列を記録する場合):

INSERT INTO AuditTable (ColumnChanged, OldValue, NewValue) /* I assume there are default columns logging who/when the change was done by? */
    SELECT 'ColumnA' as ColumnChanged, d.ColumnA, i.ColumnA
    FROM inserted i join deleted d ON d.PKID = i.PKID
    WHERE 
        /* both aren't null and the value has changed */
        (d.ColumnA IS NOT NULL AND i.ColumnA IS NOT NULL AND d.ColumnA != i.ColumnA) 
        /* it was null and now it isn't */
        OR (d.ColumnA IS NULL AND i.ColumnA IS NOT NULL) 
        /* it wasn't null and now it is */
        OR (d.ColumnA IS NOT NULL AND i.ColumnA IS NULL)
UNION 
    SELECT 'ColumnB' as ColumnChanged, d.ColumnB, i.ColumnB
    FROM inserted i join deleted d ON d.PKID = i.PKID
    WHERE 
        /* both aren't null and the value has changed */
        (d.ColumnB IS NOT NULL AND i.ColumnB IS NOT NULL AND d.ColumnB != i.ColumnB) 
        /* it was null and now it isn't */
        OR (d.ColumnB IS NULL AND i.ColumnB IS NOT NULL) 
        /* it wasn't null and now it is */
        OR (d.ColumnB IS NOT NULL AND i.ColumnB IS NULL)
....  /* continuing for each column */

行ごとに監査する方が簡単です(SQLの観点から、[書き込みが少ないため]より高速です)。つまり、次のようになります。

INSERT INTO AuditTable (OldValueA, NewValueA, OldValueB, NewValueB) 
SELECT d.ColumnA, i.ColumnA, d.ColumnB, i.ColumnB
FROM inserted i join deleted d ON d.PKID = i.PKID
WHERE 
/* same check for columnA */
    /* both aren't null and the value has changed */
    (d.ColumnA IS NOT NULL AND i.ColumnA IS NOT NULL AND d.ColumnA != i.ColumnA) 
    /* it was null and now it isn't */
    OR (d.ColumnA IS NULL AND i.ColumnA IS NOT NULL) 
    /* it wasn't null and now it is */
    OR (d.ColumnA IS NOT NULL AND i.ColumnA IS NULL)
/* now check columnB */
    (d.ColumnB IS NOT NULL AND i.ColumnB IS NOT NULL AND d.ColumnB != i.ColumnB) 
    OR (d.ColumnB IS NULL AND i.ColumnB IS NOT NULL) 
    OR (d.ColumnB IS NOT NULL AND i.ColumnB IS NULL)
....  /* continuing for each column */
于 2014-04-25T07:49:31.357 に答える