TOP

データベースsqlite3 その8

外部キー制約について

外部キー制約

あるテーブルの列が別のテーブルの列を参照しているとき、参照するテーブルのキーを参照されるテーブルのキーの外部キーと定義されます。外部キーを 持つテーブルのキーを子テーブルの子キー、参照されるテーブルのキーを親テーブルの親キーと呼ばれております。リレーショナルデータベースでは、テーブル 同士の関係性を構築する為に、外部キーが使われます。

sqliteにおける外部キー制約の概要

外部キー制約は、sqliteバージョン3.6.19(2009-10-14)で導入されました。これは、子キーが参照する親キーの存在を強制し、参照整合性が確保され、親子関係が遮断されるレコードが無いことを保証します。

利用するに当たって以下のようなことに留意する必要があります。

外部キーを有効にする

尚、複数ステートメントのトランザクション の途中で外部キー制約を有効または無効にすることはできません(SQLite が自動コミット モードでない場合)。

外部キーの宣言方法

外部キーの宣言は、列定義の後方での記述とインラインの記述の二通りがあります。

列定義の後方で記述

CREATE TABLE table_name (column_name1 [data_type] ... ,
                         column_name2 [data_type] ... ,
                             .                        .
                             .                        ,
    foreign key (set_column_name)
       references parent_table_name (parent_column_name)
               -- 複数指定の場合はカンマなしでつづけます
);

インラインで記述

親キーとなる列の条件

親キーは親テーブルの主キー(rowidを除く)またはunique制約キーである必要があります。

親キーが親テーブルの主キーである場合は列名を省略できる

上記の場合は、子キー参照の references p (p_col1)references p に省略できます。

親テーブルに存在しない親キーの外部キーは作成されますが機能しません。

外部キー制約を使用しないと、整合性を考慮しないレコードが挿入されることがあります。

サンプルデータベースで外部キー制約を確認する

下図のような親子階層関係であるテーブルをサンプルとして取り上げてみることにします。

親子階層関係図
親子階層関係図

テーブル構成

親テーブルと子テーブルは外部キー制約で関係性をもっています。parent テーブル以下の子テーブルは、すべてparent テーブルのp_col1を参照する構成となっております。

外部キー制約でinsert 、update 、delete sql文を発行してみる。

存在しない親キーを含むsqlステートメント発行はすべて失敗してしまう。

外部キーにインデックスをつけて、検索効率を上げる

外部キーは親キーに紐づけされています。子キーに対して、insert update delete する sql statementが発生した場合、内部的には検索照合処理が発生します。検索対象の外部キー列にインデックスをつけることにより、検索コストを削減でき ることが期待されます。(但し、レコード数が少ない場合は、恩恵を受けない。)

複合外部キー制約 Composite Foreign Key Constraints

複合外部キー制約は、子キーと親キーが相互に複合キーである外部キー制約です。ggrand_childの子キーとgran_child の親キーがその制約に当てはまります。

ON DELETE および ON UPDATE アクション

外部キーの ON DELETE 句と ON UPDATE 句は、親テーブルから行を削除するとき (ON DELETE)、既存の行の親キー値を変更するとき (ON UPDATE) に実行されるアクションです。

references table_name(column_name) on delete or update action_name

アクションの種類は以下のとおりになっています。アクションが明示的に指定されていない場合、デフォルトは「NO ACTION」です。

  • NO ACTION: 親キーが変更されたり、データベースから削除されたりしても、特別なアクションは実行されません。
  • RESTRICT: 親キーを削除 (ON DELETE RESTRICT の場合) または変更 (ON UPDATE RESTRICT の場合) することをブロックすることを意味します。通常の外部キー制約(即時外部キー制約)も同じようにブロックしますが、ステートメント実行終了時ではなく、 フィールドが更新されるとすぐに操作をブロックすることです。
  • SET NULL: 親キーが削除(ON DELETE SET NULLの場合)または変更(ON UPDATE SET NULLの場合)されると、その親にマッピングされている子レコードの外部キーが null に設定されます。これらのフィールドが NOT NULL に設定されている場合、エラーが発生します。
  • SET DEFAULT: 外部キー列に設定されているデフォルト値が適用されます。デフォルト値が無い場合はnullがセットされます。但し、親キーにデフォルト値が登録されている必要がある場合もあります。
  • CASCADE: 親キーに対する削除または更新操作を各従属子キーに伝播します。

親キーの更新に子キーを連動させる on update cascade

親キーの削除に連動して子キーをNULLに更新する on delete set null

child の外部キーに on delete set null を加えた、child_setnull_d、parent3を定義して動作を確認してみます。

テーブル名の変更は可能 [ALTER RENAME]

ALTER TABLE table_name RENAME TO new_table_name;

外部キーとなる列の追加は可能 [ALTER ADD]

ALTER TABLE table_name ADD COLUMN column_def...;

外部キーに on update と on delete を組み合わせた完成型

完成型のおける、外部キー制約の内容

  • 子テーブルの外部キーが親テーブルの親キーに依存しています。
  • 親テーブルから子テーブルに向かって外部キーで連結しており、階層構造になっています。
  • 親テーブルの親キーデータが変更されると、子キーも連動して更新される。
  • 親テーブル(parent)が削除されるとchild以下の子キーにnullが上書きされる。
  • 親テーブル(child)が削除されるとgrand_child以下の子キーにnullが上書きされる。
  • 親テーブル(grand_child)が削除されるとggrand_childの子キーに’null’が上書きされる。

外部キーで連結している場合、on update on delete を定義することは、テーブル間の連動を十分意識する必要があります。

遅延外部キー制約 Deferred Foreign Key Constraints [DEFERRABLE INITIALLY IMMEDIATE]

外部キーはデフォルトで「即時」に設定されており、制約に違反するステートメントは実行が完了するとすぐにエラーがトリガーされます。遅延外部キー は、COMMIT が実行されるまでエラーをトリガーしません。エラーが解消されない限りCOMMIT できないことになります。

CREATE TABLE ,,,,, REFERENCES DEFERRABLE INITIALLY IMMEDIATE

create ステートメント定義以外にも、遅延外部キー制約をpragmaの記述により、設定することが出来ます。

pragma defer_foreign_keys = ON; 
すべての外部キー制約を一時的に deferred に変更

コメントを残す

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

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