データベーストリガー(SQL Server)

ITコーディネータのシュウです。

IMG_2842

お久しぶりです。写真は4月の初め頃に撮った桜の写真です。早くブログにアップしようと思いながら、4月から新しく関わったプロジェクトのほうも忙しく、1か月があっという間に過ぎてしまいました。
さて、今年の初めには予想もしていなかったコロナウィルスの影響で、世界が全く違うものになったような現状に、本当に驚き戸惑うことが多い毎日です。ウィルスとの闘いの最先端で苦労されている医療従事者の方には本当に感謝をしなければならないと思います。ゴールデンウイークもほぼ自宅にいるという状況で、映画のDVDを借りてきて家族で見るとか、そんな過ごし方をせざるを得ない状況ではありますが、国民が一つとなってこのときを乗り越えていけるよう、そして1日も早く終息することができるように心からお祈りいたします。

<本日の題材>
データベーストリガー(SQL Server)

データベーストリガーについて、以前、Oracleで取り上げましたが、今回はSQL Serverにて同様の設定について確認してみたいと思います。
SQL Serverトリガーには、大きくは「ログオントリガー」「DDLトリガー」「DMLトリガー」の3つの種類があり、それぞれは以下のような内容になります。
「ログオントリガー」は、ログオン時ユーザーセッションが確立されるときに実行するもの
「DDLトリガー」は、DDL操作(CREATE, ALTER, DROPなど)により起動するもの
「DMLトリガー」は、特定の表やビューに対してDML操作(INSERT, UPDATE, DELETEなど)が行われるときに起動するもの

前回、Oracleで「DMLトリガー」の「AFTERトリガー」を使った例を紹介しましたが、今回はSQLServerで同様の設定をしてみたいと思います。

例)
前回同様、ユーザー管理用の「ACCOUNTS」テーブルというものがあったとして、それに対しての、INSERT, UPDATE, DELETE が行われるタイミング(AFTER)で、処理のログを「ACCOUNTS_LOG」テーブルに登録するトリガーを作成してみます。
まず、処理のログを登録する「ACCOUNTS_LOG」テーブルを作成します。

CREATE TABLE accounts_log(
log_date DATE,
old_account_id INT,
new_account_id INT,
old_name NVARCHAR(20),
new_name NVARCHAR(20),
action NVARCHAR(20));

次に、トリガーを作成しますが、「ACCOUNTS」テーブルに対しての、INSERT, UPDATE, DELETE が行われてデータが更新されるたびに、「ACCOUNTS_LOG」テーブルに、処理日、変更前後の「ACCOUNT_ID」、「NAME」そして処理内容を記録させます。

--INSERT、DELETEの履歴登録用
CREATE TRIGGER accounts_ins_del_trigger
ON accounts
AFTER INSERT, DELETE
AS
BEGIN
INSERT INTO accounts_log (log_date, old_account_id, new_account_id, old_name, new_name, action)
SELECT GETDATE(), NULL, account_id, NULL, name, 'INSERT'
FROM inserted
UNION
SELECT GETDATE(), account_id, NULL, name, NULL, 'DELETE'
FROM deleted;
END;
GO

--UPDATEの履歴登録用
CREATE TRIGGER accounts_upd_trigger
ON accounts
AFTER UPDATE
AS
BEGIN
INSERT INTO accounts_log (log_date, old_account_id, new_account_id, old_name, new_name, action)
SELECT GETDATE(), account_id, NULL, name, NULL, 'UPDATE'
FROM deleted
UNION
SELECT GETDATE(), NULL, account_id, NULL, name, 'UPDATE'
FROM inserted
END;
GO

前回同様下記のように、「ACCOUNTS」テーブルへのデータの登録、修正、削除を順に行ってみます。

INSERT INTO accounts(account_id, name) VALUES(101, '山田 太郎');
INSERT INTO accounts(account_id, name) VALUES(102, '高橋 三郎');
UPDATE accounts SET NAME = '高橋 一郎' WHERE account_id = 102;
DELETE FROM accounts WHERE account_id = 101;

それでは、「ACCOUNTS_LOG」テーブルを確認してみます。
SELECT * FROM accounts_log
ORDER BY log_date;

accounts_log

たしかに、「ACCOUNTS_LOG」テーブルへの更新履歴が登録されています

ここで、SQL Serverの場合、DML トリガーステートメントでは、deleted テーブルおよび inserted テーブルという 2 つの特殊なテーブルが使用されます。そして、deleted テーブルには、DELETE ステートメントと UPDATE ステートメントの実行で影響を受けた行のコピーが格納され、inserted テーブルには、INSERT ステートメントおよび UPDATE ステートメントの実行で影響を受けた行のコピーが格納されるかたちになります。 つまり、UPDATEという更新処理は、DELETEの削除処理とそれに続くINSERTの挿入処理の組み合わせと考えることができ、deleted テーブルに古い行がコピーされ、その後、新しい行がinsertedテーブルにコピーされることになります。

そのため、「ACCOUNTS_LOG」テーブルへの更新履歴には、UPDATEに関しては、from deleted、from inserted からログを取得するようにトリガーを作っています。更新履歴にも、UPDATE処理により削除、登録の2つの行が確認できます。

 

今日は以上まで


にほんブログ村 IT技術ブログへ
にほんブログ村