TOP

データベースsqlite3 その9

トリガー処理について

トリガー処理基本

sql文の実行は、指定したテーブル以外にその実行が引き金になって、別のsql文を実行するような仕組みを備えております。たとえば、あるレコードが挿入されたときに、そのレコード数の定義されているテーブルの列がカウントアップするsql文が発行されるような場合が、これにあたります。

外部キー制約においても、このような関連のあるテーブルの列に作用するような仕組みがありますが、上記のようなsql文実行によるものではない点で異なる仕組みといえます。

トリガーアクションとは、sql文によって指定されたデータベース イベントが発生したときに自動的に実行されるデータベース操作ということです。

SQLITE3 トリガー構文

CREATE TRIGGER trigger_name [BEFORE|AFTER] INSERT ON table name  or
CREATE TRIGGER trigger_name [BEFORE|AFTER] DELETE ON table name  or
CREATE TRIGGER trigger_name [BEFORE|AFTER] UPDATE OF column name ON table name
BEGIN
 -- Trigger logical sentences.
END;
/*
  テーブルに対する処理が行なわれるWHERE句直前と直後の値は、「OLD.カラム名」「NEW.カラム名」で取得できます。
insert trigger の場合 new.列名
update trigger の場合 old.列名 new.列名
delete trigger の場合 old.列名
 として利用できます。
DROP TRIGGER trigger_name;  トリガー解除
  WHEN 句が指定されている場合、指定された SQL ステートメントは、WHEN 句が真である行に対してのみ実行されます。WHEN 句が指定されていない場合、SQL ステートメントはすべての行に対して実行されます。
  変更するテーブルは、トリガーが関連付けられているテーブルまたはビューと同じデータベースに存在する必要があり
*/

CREATE TRIGGER trigger_name [BEFORE|AFTER] INSTEAD OF column name ON view table name
BEGIN
 -- Trigger logical sentences.
END;
読み取り専用ビューからトリガーを発行し、トリガー文においてテーブル列に変更を加える構文

SQLITE3トリガーアクションについて

以下のような事項に留意する必要があります。

  • トリガーは、 DELETE、UPDATE、INSERTのいずれかの操作に対して起動することを指定する必要があります。
  • SQL文を実行する前 (BEFORE)、SQL文を実行する後(AFTER)のタイミングを指定します。
  • TEMP 以外のトリガーの場合、変更またはクエリを実行するテーブルは、トリガーが接続されているテーブルまたはビューと同じデータベース内に存在する必要があります。
  • WHEN 句が指定されている場合、指定された SQL ステートメントは、WHEN 句が真である行に対してのみ実行されます。WHEN 句が指定されていない場合、SQL ステートメントはすべての行に対して実行されます。
  • 関連付けられているテーブルが削除されると、トリガーは自動的に削除されます。

トリガー構文チュートリアル

ターミナルウィンドウを開き、ドットコマンドを使ってトリガー処理を確認してみます。

題材

自分が作った記事をテーブルmy_contentsに落とし、管理します。記事には、タイトルとページ数とジャンルを書き込みます。それとは別に、 ジャンルを管理するテーブルmy_junleを作ります。ジャンル名とカウント数を管理します。それぞれ、id junle_idというプライマリーキーをもち、my_contentsのjunle列はmy_junleのjunle_idを参照しています。但し、今 回は外部キー制約は使っていません。my_junleのカウント数をトリガーにより書き込み処理します。

テーブル生成

my_junleテーブルにデータを入れる

insertトリガー生成

deleteトリガー生成

updateトリガー

instead トリガー

セルフテスト

sqlite3にはsqlステートメントをテストする機能が備わっております。アプリケーション側でも各種のテストが行われますが、端末でテストすることがある場合は、有用になるのではないかと思います。

ここでは、ドットコマンドを用いて、作成したトリガー文をテストしてみます。

.selftest ?OPTIONS?      Run tests defined in the SELFTEST table
    Options:
       --init               Create a new SELFTEST table
       -v                   Verbose output
.testcase NAME           Begin redirecting output to 'testcase-out.txt'
 

selftest テーブル生成

initコマンドオプションでselftestテーブルが生成されます。sqlステートメントの検証は、このテーブルにテストコードを挿入することで実現できます。但し、以下の事がテストコードの定義をしなくても、実行されます。

  • sqlite_schema テーブルのコンテンツに対してのSHA3ハッシュ値が生成される。①
  • すべてのテーブルのコンテンツのハッシュ値が生成される。 ②
  • データベースの低レベルのフォーマットと整合性チェックが行われます。sql構文として正しくなければ、エラーの個数が返されます。エラーが見つからなかった場合は、値「ok」を持つ 1 つの行が返されます。③

ハッシュ値をエントリーすることにより、このセルフテスト対象データベースのテーブルの内容に変更が無いことを保証するのに使われます。ここでは、ハッシュ値の比較を行いませんが、次回以降にセルフテストを行うようなことがあれば、利用するのも良いでしょう。

selftestテーブルの構成

テスト結果の出力

selftestコマンドで、selftestテーブルに挿入されたテスト結果が出力されます。.testcaseは、testcase-out.txtというファイル名でカレントフォルダーにファイル出力するコマンドです。

ターゲットとなるテーブルの内容を出力する。

テスト内容を挿入する

selftesttテーブルのop句が’memo’の場合は、以下のフォーマットで出力することにします。

[test$numbers]$test_name => Excepted$tno; $Expected
 $numbersはターゲットテストのテスト番号(tno) 複数ある場合はtno1-tnoN
 $test_nameはテストの名称
 $tnoはテスト番号
 SExpectedは出力結果と比較する為の期待値

どんなテストが行われたかを記録しなければ、testcaseコマンド、memoオペレーション、selftestテーブルのselect文を省略しても良いと思います。端末画面にテスト検証結果が出力されるだけになります。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください