外部キーと複合キー (2) 親子孫の関係

最終更新日: 2022年7月4日

設定方法

想定するモデル関係を図に示します。親モデルAと子モデルBの関係は前ページの説明をお読みください。

孫モデルCは、モデルAの主キー値がとりうる値の範囲(定義域)とモデルBの主キー値がとりうる値の範囲(定義域)、そして連番(順序値)の組み合わせとします。

モデルの関係

用意するモデルは三つです。

用意する親子孫モデル

モデルC

モデルA,モデルBの主キー値を含みます。

項目名 項目ID 外部キー その他
モデルBがもつモデルAの主キー(読み込み専用) MODELA_PKEY_MODELB 数値 モデルBの「モデルAの主キーを自身のキーとする」 新規登録画面でも変更できないよう、読み込み専用とする。
モデルBがもつモデルBの主キー(読み込み専用) MODELB_PKEY 数値 モデルBの「モデルBの主キー」 新規登録画面でも変更できないよう、読み込み専用とする。
モデルCの主キー MODELC_PKEY 数値 - 順序値とする。
モデルC (孫)

MODELA_PKEY_MODELB 項目は MODELA の主キー値を格納するため、MODELA の主キーの型と同じ整数型とします。主キーかつ外部キーの設定を行います。

モデルC (孫) 主キーの設定 (1)

登録画面や更新画面で値の変更が行えないよう、読み込み専用の設定を行います。

読み込み専用の設定

この項目は主キーなので更新画面では自動的に読み込み専用扱いになります。ここでは新規登録画面を含む、どの画面でも確実に読み込み専用とするため「全画面」を指定しています。

MODELB_PKEY 項目は MODELB の主キー値を格納するため、MODELB の主キーの型と同じ整数型とします。主キーかつ外部キーの設定を行います。

モデルC (孫) 主キーの設定 (2)

MODELC_PKEY 項目も主キー項目で、順序を使うとします。

モデルC (孫) 主キーの設定 (3)

モデル参照を使わないのはなぜ?

ここではモデルCの主キーとして、モデルBの主キーを参照する設定は使っていません。複合主キーのモデルBを参照する方法は、定義上の項目は1つなので外部キーの設定ができないためです。

モデルC (孫) 主キーで、モデルBを参照する項目を用意した場合
モデル参照(検索)の設定
外部キー設定ができない(見た目上は1項目だが、実体は2つある。割り当てができない)

動作例

モデルBの詳細画面に、モデルCの新規作成を行うボタンが用意されます。これはモデルBとモデルCの間に外部キーの関係を設定したためです。

モデルBの詳細画面にモデルCの新規作成ボタンが用意される

モデルCの新規作成画面です。モデルBの主キー値が転記されています。かつ、これらの値は変更不可となっているため、この時点で子モデルBと孫モデルCの関係が確定しています。

モデルCの新規登録画面

モデルCの新規作成を行ってみます。

モデルCを作成する

モデルCの詳細画面では、順序値が割り当てられた項目「モデルCの主キー」も確認できます。

モデルCの詳細画面

モデルBの詳細画面では、自身に紐づくモデルCの一覧が表示されます。

モデルBの詳細画面

モデルBの別データを表示した例です。別モデル(ここでは「モデルBの主キー」値が1001のデータ)と紐づく、モデルCだけが表示されていることがわかります。

もう一つのモデルBの詳細画面

テーブル定義

モデルA,モデルB,モデルCに関するテーブル定義は次のとおりです。親、子、孫の関係にあわせてそれぞれの主キー項目を保持していることがわかります。

create table "MODELA" (
    "MODELA_PKEY" integer not null,
    "NAME" varchar(255),
    "MEMO" varchar(255),
    primary key ("MODELA_PKEY")
);
create table "MODELB" (
    "MODELA_PKEY" integer not null,
    "MODELB_PKEY" integer not null,
    "NAME" varchar(255),
    "MEMO" varchar(255),
    primary key ("MODELA_PKEY", "MODELB_PKEY")
);
create table "MODELC" (
    "MODELA_PKEY_MODELB" integer not null,
    "MODELB_PKEY" integer not null,
    "MODELC_PKEY" integer not null,
    "NAME" varchar(255),
    "MEMO" varchar(255),
    primary key ("MODELA_PKEY_MODELB", "MODELB_PKEY", "MODELC_PKEY")
);