これらの要件が標準であるかどうかはわかりませんが、次のことを実行できるソリューションがあるかどうか疑問に思っています。
- 指定された一連のテーブルについて、関連するテーブルの監査バージョンでレコードを変更する前に、レコードのコピーを保持します。
すべてのテーブルに対してこれをコーディングする必要はありません。これを行う SQL Server の上にインストールできるソリューションがあるかどうか疑問に思っていますか?
これらの要件が標準であるかどうかはわかりませんが、次のことを実行できるソリューションがあるかどうか疑問に思っています。
すべてのテーブルに対してこれをコーディングする必要はありません。これを行う SQL Server の上にインストールできるソリューションがあるかどうか疑問に思っていますか?
次のクラス図に示すようにBook
、監査ログ情報をテーブルに格納する必要があるテーブルがあるとします。BookAuditLog
BookAuditLog
テーブルは次のように作成されます。
CREATE TABLE BookAuditLog (
BookId bigint NOT NULL,
OldRowData nvarchar(1000) CHECK(ISJSON(OldRowData) = 1),
NewRowData nvarchar(1000) CHECK(ISJSON(NewRowData) = 1),
DmlType varchar(10) NOT NULL CHECK (DmlType IN ('INSERT', 'UPDATE', 'DELETE')),
DmlTimestamp datetime NOT NULL,
DmlCreatedBy varchar(255) NOT NULL,
TrxTimestamp datetime NOT NULL,
PRIMARY KEY (BookId, DmlType, DmlTimestamp)
)
テーブルのBookAuditLog
列には、次のデータが格納されます。
BookId
た関連行の識別子が格納されます。Book
OldRowData
の JSON 表現を格納します。Book
NewRowData
のレコード状態の JSON 表現を格納します。Book
DmlType
を作成、更新、または削除した DML ステートメント タイプを格納する列挙列ですBook
。DmlTimestamp
、DML ステートメントの実行タイムスタンプを格納します。DmlCreatedBy
INSERT、UPDATE、または DELETE DML ステートメントを発行したユーザーを格納します。TrxTimestamp
を変更したトランザクションのタイムスタンプを保存します。Book
INSERT、UPDATE、および DELETE DML ステートメントをキャプチャするには、BookAuditLog
テーブルにレコードを挿入する 3 つのデータベース トリガーを作成する必要があります。
Book
テーブルの INSERT ステートメントをインターセプトするために、TR_Book_Insert_AuditLog
トリガーを作成します。
CREATE TRIGGER TR_Book_Insert_AuditLog ON Book
FOR INSERT AS
BEGIN
DECLARE @loggedUser varchar(255)
SELECT @loggedUser = CAST(SESSION_CONTEXT(N'loggedUser') AS varchar(255))
DECLARE @transactionTimestamp datetime = SYSUTCdatetime()
INSERT INTO BookAuditLog (
BookId,
OldRowData,
NewRowData,
DmlType,
DmlTimestamp,
DmlCreatedBy,
TrxTimestamp
)
VALUES(
(SELECT id FROM Inserted),
null,
(SELECT * FROM Inserted FOR JSON PATH, WITHOUT_ARRAY_WRAPPER),
'INSERT',
CURRENT_TIMESTAMP,
@loggedUser,
@transactionTimestamp
);
END
Book
レコードの UPDATE ステートメントを取得するために、次のTR_Book_Update_AuditLog
トリガーを作成します。
CREATE TRIGGER TR_Book_Update_AuditLog ON Book
FOR UPDATE AS
BEGIN
DECLARE @loggedUser varchar(255)
SELECT @loggedUser = CAST(SESSION_CONTEXT(N'loggedUser') AS varchar(255))
DECLARE @transactionTimestamp datetime = SYSUTCdatetime()
INSERT INTO BookAuditLog (
BookId,
OldRowData,
NewRowData,
DmlType,
DmlTimestamp,
DmlCreatedBy,
TrxTimestamp
)
VALUES(
(SELECT id FROM Inserted),
(SELECT * FROM Deleted FOR JSON PATH, WITHOUT_ARRAY_WRAPPER),
(SELECT * FROM Inserted FOR JSON PATH, WITHOUT_ARRAY_WRAPPER),
'UPDATE',
CURRENT_TIMESTAMP,
@loggedUser,
@transactionTimestamp
);
END
Book
テーブル行の DELETE ステートメントをインターセプトするために、次のTR_Book_Delete_AuditLog
トリガーを作成します。
CREATE TRIGGER TR_Book_Delete_AuditLog ON Book
FOR DELETE AS
BEGIN
DECLARE @loggedUser varchar(255)
SELECT @loggedUser = CAST(SESSION_CONTEXT(N'loggedUser') AS varchar(255))
DECLARE @transactionTimestamp datetime = SYSUTCdatetime()
INSERT INTO BookAuditLog (
BookId,
OldRowData,
NewRowData,
DmlType,
DmlTimestamp,
DmlCreatedBy,
TrxTimestamp
)
VALUES(
(SELECT id FROM Deleted),
(SELECT * FROM Deleted FOR JSON PATH, WITHOUT_ARRAY_WRAPPER),
null,
'DELETE',
CURRENT_TIMESTAMP,
@loggedUser,
@transactionTimestamp
);
END
Book
テーブルで INSERT ステートメントを実行する場合:
INSERT INTO Book (
Author,
PriceInCents,
Publisher,
Title,
Id
)
VALUES (
'Vlad Mihalcea',
3990,
'Amazon',
'High-Performance Java Persistence 1st edition',
1
)
テーブルBookAuditLog
で実行されたばかりの INSERT ステートメントをキャプチャするレコードが挿入されていることがわかります。Book
| BookId | OldRowData | NewRowData | DmlType | DmlTimestamp | DmlCreatedBy | TrxTimestamp |
|--------|------------|------------------------------------------------------------------------------------------------------------------------------------|---------|-------------------------|---------------|-------------------------|
| 1 | | {"Id":1,"Author":"Vlad Mihalcea","PriceInCents":3990,"Publisher":"Amazon","Title":"High-Performance Java Persistence 1st edition"} | INSERT | 2020-11-08 08:40:28.343 | Vlad Mihalcea | 2020-11-08 06:40:28.347 |
Book
表の行を更新する場合:
UPDATE Book
SET PriceInCents = 4499
WHERE Id = 1
テーブルBookAuditLog
の AFTER UPDATE トリガーによって新しいレコードが追加されることがわかります。Book
| BookId | OldRowData | NewRowData | DmlType | DmlTimestamp | DmlCreatedBy | TrxTimestamp |
|--------|------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------|---------|-------------------------|---------------|-------------------------|
| 1 | | {"Id":1,"Author":"Vlad Mihalcea","PriceInCents":3990,"Publisher":"Amazon","Title":"High-Performance Java Persistence 1st edition"} | INSERT | 2020-11-08 08:40:28.343 | Vlad Mihalcea | 2020-11-08 06:40:28.347 |
| 1 | {"Id":1,"Author":"Vlad Mihalcea","PriceInCents":3990,"Publisher":"Amazon","Title":"High-Performance Java Persistence 1st edition"} | {"Id":1,"Author":"Vlad Mihalcea","PriceInCents":4499,"Publisher":"Amazon","Title":"High-Performance Java Persistence 1st edition"} | UPDATE | 2020-11-08 08:43:22.803 | Vlad Mihalcea | 2020-11-08 06:43:22.807 |
Book
表の行を削除する場合:
DELETE FROM Book
WHERE Id = 1
テーブルBookAuditLog
の AFTER DELETE トリガーによって新しいレコードが追加されます。Book
| BookId | OldRowData | NewRowData | DmlType | DmlTimestamp | DmlCreatedBy | TrxTimestamp |
|--------|------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------|---------|-------------------------|---------------|-------------------------|
| 1 | | {"Id":1,"Author":"Vlad Mihalcea","PriceInCents":3990,"Publisher":"Amazon","Title":"High-Performance Java Persistence 1st edition"} | INSERT | 2020-11-08 08:40:28.343 | Vlad Mihalcea | 2020-11-08 06:40:28.347 |
| 1 | {"Id":1,"Author":"Vlad Mihalcea","PriceInCents":3990,"Publisher":"Amazon","Title":"High-Performance Java Persistence 1st edition"} | {"Id":1,"Author":"Vlad Mihalcea","PriceInCents":4499,"Publisher":"Amazon","Title":"High-Performance Java Persistence 1st edition"} | UPDATE | 2020-11-08 08:43:22.803 | Vlad Mihalcea | 2020-11-08 06:43:22.807 |
| 1 | {"Id":1,"Author":"Vlad Mihalcea","PriceInCents":4499,"Publisher":"Amazon","Title":"High-Performance Java Persistence 1st edition"} | | DELETE | 2020-11-08 08:44:25.630 | Vlad Mihalcea | 2020-11-08 06:44:25.633 |
ApexSQL Auditなどのサード パーティ製のポイント アンド クリック トリガー ベースのソリューションを試すことができます。ApexSQL Auditは SQL Server データベース用の監査ツールであり、データベースで発生したデータ変更を、誰が変更したか、どのオブジェクトが変更されたかに関する情報を含めてキャプチャします。いつ変更されたか、および変更に使用された SQL ログイン、アプリケーション、およびホストに関する情報。キャプチャされたすべての情報を中央リポジトリに保存し、印刷に適した形式でエクスポートします
免責事項: 私は ApexSQL で製品サポート エンジニアとして働いています。
この記事をご覧ください - SQL Server 2008 での監査では、 SQL Server 2008 に既に存在する監査機能を見事に活用しています。
また、@Microtechie の回答が素晴らしい記事を示していることにも言及する必要があります。それらを読んで、どちらが適応しやすいかを判断してください。
トリガーを見てください。これらを使用して、要件に合わせて何かを実装できます。
データベース スナップショットを使用すると、データの読み取り専用コピーをその瞬間に保持できます。また、ログのバックアップを使用すると、必要に応じて特定の期間に情報を復元できます。
ログから情報を読み取って、変更された情報を取得することもできます。
あなたの好みではない他の解決策は、トリガーを使用して変更を追跡することですが、各テーブルで作業する必要がある場合があります。Change Data Capture 機能を有効にして変更を検出することもできます。この機能もテーブルごとに有効にする必要がありますが、必要なコードはトリガーよりも少なくなります。
最後に、 Apex SQL Triggerのような、数回のクリックと構成で自動的にこのジョブを実行するサードパーティ ツールがあります。