この記事では、データベーススペシャリスト試験の対策として、『参照制約』についての問題を扱った過去問の解説を紹介します。対象は、平成30年度午後1問2の問題となります。
問1(SQL問題のため解説なし)
設問2(1)


設問2(1)は、参照制約における制約検査での処理結果(正常終了/エラー)について回答する問題。
〔RDMSの主な仕様〕の「1.参照制約」に仕様が記載してある。
<回答方式>
・(a)、(b)の処理結果について、エラーの場合は理由も答える
<条件>
・(a);新規従業員登録のために、所属未定(部署コード;NULL)の行を”従業員”テーブルに挿入
テーブル名;従業員の列名;部署コード、参照先;部署(部署コード)、実行契機;UPDATE、挙動モード;NO ACTION、検査契機モード;猶予モード(表3「参照制約機能の利用案」から)
・(b);ある部署の管理職退職に伴い、”従業員”テーブルから当該従業員を削除
テーブル名;部署、列名;管理者従業員コード、参照先;従業員(従業員コード)、実行契機;DELETE、挙動モード;NO ACTION、検査契機モード;即時モード(表3「参照制約機能の利用案」から)
<回答>
(a)について、表3「参照制約機能の利用案」から、
・「テーブル名;従業員、列名;部署コード、参照先;部署(部署コード)、実行契機;UPDATE、挙動モード;NO ACTION、検査契機モード;猶予モード」であることが分かる。
参照制約における、参照先テーブルの外部キー追加時の処理のポイントは、参照元の外部キーとして設定されている場合かNULL(非NULL設定をしていない場合に限り)しか設定できない。
今回の場合は、非NULLが設定されていないので、外部キー追加時の処理ポイントを満たしている。
したがって、処理結果は『正常終了』となる。
参照先テーブル(部署);問題なく実行可能
参照元テーブル(従業員);挙動モードの確認が必要?→
(b)について、表3「参照制約機能の利用案」から、
「テーブル名;部署、列名;管理者従業員コード、参照先;従業員(従業員コード)、実行契機;DELETE、挙動モード;NO ACTION、検査契機モード;即時モード」であることが分かる。
参照制約における、参照先テーブルの外部キー削除時の処理のポイントは、参照元の外部キーとして設定されている場合(NULLでない場合)、削除できない。
テーブル仕様の挙動モード;NO ACTIONとなっており、参照元テーブルに対して何もしないこととなる。挙動モード;CASCADEの場合は、参照元テーブルも削除を連鎖させるので、参照元・参照先ともになくなり、参照制約のポイントに違反せず、処理は正常終了する。
したがって、今回の場合、処理結果は『エラー』となり、理由は、『”部署”テーブルの管理者従業員コードの参照制約に違反するから』や『参照先(従業員)テーブルの外部キー(従業員コード)を削除した結果、参照元テーブル(部署)に存在する外部キー(管理者従業員コード)に対しては出来ないという参照制約に違反するから』となる。。
外部キーの処理による違いのポイント
⬛︎外部キーの処理による違いのポイント;参照制約の基本事項
・追加時;すでに存在するものかNULL
・削除時;そのテーブルの外部キーが削除されるだけ
| 操作対象 | 操作内容 | 主な制約チェック | 挙動(エラー or 正常) | 備考 |
|---|---|---|---|---|
| 参照先(親) | 追加(INSERT) | 特に参照制約なし(他から参照される側) | 常に正常終了 | 子テーブルから参照される可能性があるキーを追加 |
| 参照先(親) | 削除(DELETE) | 子テーブルに対応する外部キーが存在するか | – 子に該当行がある → 制約違反(RESTRICT/NO ACTION)- CASCADE → 子も削除- SET NULL → 子の外部キーがNULLになる | 「ON DELETE」の指定で挙動が変化する |
| 参照元(子) | 追加(INSERT) | 外部キーの値が参照先に存在するか、またはNULLか | – 存在 or NULL → 正常- 存在しない → 制約違反 | もっとも典型的な参照整合性チェック |
| 参照元(子) | 削除(DELETE) | 特に制約なし(外部キーを削除するだけ) | 常に正常終了 | 親には影響しない(片方向の制約) |
| 操作 | 参照制約の基本ルール | 挙動モード: NO ACTIONの挙動 | 挙動モード: CASCADEの挙動 |
| 追加 (INSERT/UPDATE) | 外部キーに設定する値は、参照先テーブルの主キーに存在するか、NULLを許容している場合はNULLでなければならない。 | 参照先に存在しない値や、NULL不可の列へのNULL値の挿入・更新を拒否する。 | 参照元への挿入・更新操作であり、参照先に対するアクションはないため、NO ACTIONと同様に基本ルールに違反すれば拒否する。 |
| 削除/更新 (DELETE/UPDATE) | 参照先テーブルの主キーは、他のテーブルの外部キーから参照されていない場合に限り削除・更新できる。(または、参照されている場合も連鎖的な処理を行う) | 参照元テーブルの外部キーによって参照されている場合、操作そのものをエラーで拒否する。 | 参照先テーブルの主キーが削除・更新された場合、参照元テーブルの外部キーも連鎖的に削除・更新する。これにより参照制約の違反を防ぎ、操作は正常終了する。 |



設問2(2)

設問2(2)は、トリガと参照制約の関係による不具合の対策に関する問題である。
<条件>
・不具合発生トリガ;”従業員”テーブル及び”従業員家族”テーブルから退職した従業員の行を削除して別テーブルに保存
・”従業員”テーブルのトリガ定義を変更した上で、新たなトリガを定義
・トリガの仕様(〔RDBMSの主な仕様〕の「2.トリガ」参照)
・テーブル名;従業員家族、列名;従業員コード、参照先;従業員(従業員コード)、実行契機;DELETE、挙動モード;CASCADE、検査契機モード;即時モード(表3「参照制約機能の利用案」から)
<現状のトリガ>
・実行タイミング;”従業員”テーブルの削除の後
・トリガの処理;
①削除した”従業員”テーブルの行を別テーブルに挿入
②”従業員家族”テーブルの家族行を別テーブルに挿入し、その後削除
<回答方式>
新たなトリガについて下記を回答
・対象となるテーブルのテーブル名
・実行タイミング
・処理内容
<回答>
不具合内容について考察。
表3「参照制約機能の利用案」から、「テーブル名;従業員家族、列名;従業員コード、参照先;従業員(従業員コード)、実行契機;DELETE、挙動モード;CASCADE、検査契機モード;即時モード」となっており、現状のトリガの「”従業員”テーブルの削除の後」で、参照元の’従業員家族’テーブルの”従業員コード”がCASCADEで削除されることとなっている。
図1「主なテーブル構造」から”従業員家族”テーブルの主キーの一部は”従業員コード”であり、保持していた従業員家族の行が失われてしまう。そのため、トリガの処理「②”従業員家族”テーブルの家族行を別テーブルに挿入し、その後削除」が出来ず、これが不具合と考えられる。整理すると、現状のトリガの問題点としては、次になる。
□「実行タイミング;”従業員”テーブルの削除の後」(CASCADEにより、”従業員家族”テーブル対象行がなくなり、トリガ処理を実行できない)
「”従業員”テーブルのトリガ定義を変更した上」とあるので、どう変更するか考える。まず、対応が必要になるのは、「実行タイミング;”従業員”テーブルの削除の後」に関してである。このタイミングでは、以降の処理が実行できないので、変更する。
それが、新たに定義するトリガとなる。
「”従業員家族”テーブルの家族行を別テーブルに挿入し、その後削除」出来ないことが問題となっている。「”従業員家族”テーブルの家族行を別テーブルに挿入」した後、削除すれば他の制約に引っかかることなく終了できる。したがって、トリガの対象テーブル『従業員家族』を実行タイミング『削除した後』とし、処理内容を『別テーブルに挿入する』とする。
ポイント
- 参照制約(CASCADE) は参照元の行を自動削除してしまう。
- そのため「親表削除後のトリガ」では参照元のデータが残っておらず、後続処理ができないことがある。
- 対策:
- トリガを「参照元テーブル(従業員家族)」側に定義する
- タイミングを「削除後(AFTER DELETE)」にする
- この順序なら、削除される直前の行データ(:OLD 値)を使って別テーブルへ退避できる



設問3(1)

設問3(1)は、更新手順の設計ミスによる不具合の内容の説明問題である。
<条件>
・図3「参照制約機能を利用する以前の更新手順」参照
・テーブル名;従業員の列名;部署コード、参照先;部署(部署コード)、実行契機;DELETE、挙動モード;CASCADE、検査契機モード;猶予モード(表3「参照制約機能の利用案」参照)
<回答>
表3「参照制約機能の利用案」を参照すると、「テーブル名;従業員|列名;部署コード、参照先;部署(部署コード)、実行契機;UPDATE、挙動モード;NO ACTION、検査契機モード;猶予モード」であると分かる。図3「参照制約機能を利用する以前の更新手順①」を参照すると「”部署”テーブルから不要な行を削除」とある。つまり、”部署”テーブルから行を削除した際、CASCADEにより、参照元の”従業員”テーブルの”部署コード”も削除される。よって、「⑤”従業員”テーブルの部署コードを更新」を前に、更新すべき行がない状態となってしまう不具合が発生する。
したがって、契機『①』で、『』
<問題>
・参照先テーブルの外部キーが削除されると、設問3(1)は、更新手順の設計ミスによる不具合の内容の説明問題である。
<条件>
・図3「参照制約機能を利用する以前の更新手順」参照
・テーブル名;従業員の列名;部署コード、参照先;部署(部署コード)、実行契機;DELETE、挙動モード;CASCADE、検査契機モード;猶予モード(表3「参照制約機能の利用案」参照)
<回答>
表3「参照制約機能の利用案」を参照すると、「テーブル名;従業員|列名;部署コード、参照先;部署(部署コード)、実行契機;UPDATE、挙動モード;NO ACTION、検査契機モード;猶予モード」であると分かる。図3「参照制約機能を利用する以前の更新手順①」を参照すると「”部署”テーブルから不要な行を削除」とある。
つまり、”部署”テーブルから行を削除した際、CASCADEにより、参照元の”従業員”テーブルの”部署コード”も削除される。候補キーの一部の”部署コード”が削除されることにより、対象の候補キーを含む行は削除される。よって、「⑤”従業員”テーブルの部署コードを更新」を前に、更新すべき行がない状態となってしまう不具合が発生する。
したがって、契機『①』で、『削除された部署に所属していた従業員が”従業員”テーブルから削除される』という不具合が発生する。
ポイント
<ポイント>
・参照先テーブルの外部キーが削除されると、CASCADEにより、参照元テーブルの外部キーの元となった候補キーの『行全体』が削除される。候補キーが削除されることにより、行も削除される訳ではなし。→DELETEのCASCADEでは”行ごと”削除
・参照元テーブルの外部キーが削除された場合、参照元テーブルの外部キーがNULLとなるだけ。
参照制約のDELETE操作ポイント整理
| 操作対象のテーブル | 削除される行/キーの役割 | 挙動モード | 結果と正確な動作 |
参照先(親) (部署) の行を削除 | 主キー (部署コード) の行を削除 | CASCADE | 参照元 (従業員) の対応する行(外部キー含む)が、行全体で連鎖的に削除されます。外部キー列だけが削除されるわけではありません。 |
参照先(親) (部署) の行を削除 | 主キー (部署コード) の行を削除 | SET NULL | 参照元 (従業員) の対応する行の外部キー (部署コード) の値がNULLに更新されます。行自体は削除されません。 |
参照元(子) (従業員) の行を削除 | 外部キー (部署コード) を含む行全体を削除 | (モード無関係) | 正常終了。参照制約違反は発生せず、参照先(部署)の主キーはそのまま維持されます。外部キーの値は「NULLになる」のではなく、**「値ごと消滅」**します。 |


設問3(2)

<問題>
設問3(2)は(1)の不具合解消のための順序を答える問題。
<回答>
先に部署を削除することで、削除する部署に所属していた従業員が削除されるのが問題なので、先に”従業員”テーブルの”部署コード”を変えて、その後に不要な”部署コード”を削除すれば、従業員は削除されない。
したがって、『③”部署”テーブルに新規行を追加→⑤’従業員’テーブルの”部署コード”を更新→①”部署”テーブルから不要な行(不要な部署)を削除』となる。
ポイント
・『新規行挿入』→『更新』→『削除』;不具合なし
・『削除』→『更新』→『新規行追加』;削除時に参照元テーブルも一緒に削除される(CASCADEの場合)
更新手順の安全性のポイント
| 手順の原則 | 動作の安全性 | 理由(CASCADE設定時) |
| 新規 → 更新 → 削除 | 安全 | 更新(異動)を先に行うことで、後の削除操作から従業員データを切り離し、連鎖削除を防ぐ。 |
| 削除 → 更新 → 新規 | 不安全 | 削除を先に行うとCASCADEで行全体が消滅し、その後の更新操作が不可 |
設問3(3)

<問題>
設問3(3)は、参照制約;猶予モードにおける更新時の振る舞いについての問題。
<条件>
・”従業員”テーブルの”部署コード”の参照制約;猶予モード
・”部署”テーブルの”部署コード”を更新した時
・(a)猶予モードの制約検査はどのようなものか?
・(b)(a)の検査の際、処理時間が長くなると予想される理由は?
<回答>
まず、(a)について、処理の確認する。
表3「参照制約機能の利用案」から「テーブル名;従業員の列名;部署コード、参照先;部署(部署コード)、実行契機;UPDATE、挙動モード;NO ACTION、検査契機モード;猶予モード」となっている。
”部署”テーブルの”部署コード”更新SQL実行時、挙動モード;NO ACTIONのため、”従業員”(参照元)テーブルには反映されない。
全SQLの終了後、トランザクション終了時、検査契機モード;猶予モードが適用される。この時行われるのは、『参照制約違反かどうか』 である。つまり、参照先の”部署コード”を更新した場合、参照元の”部署コード”は『参照先の”部署コード”になっているか』もしくは『NULL(非NULL制約はない上で)』になっている必要がある。
したがって、『更新によって無くなった部署コードが、”従業員”テーブルの”部署コード”に存在しないことを確認する』や『猶予モードでは、トランザクション終了時に、従業員テーブルの部署コードがすべて、部署テーブルの部署コード(またはNULL)に対応しているかをまとめて検査する』となる。
次に(b)処理時間が長くなると考えられる理由について考える。
今回の場合、”従業員”テーブルの”部署コード”について、検査することになるが、この処理のために対象の”部署コード”に絞って検査するのが最も早い。
しかし、〔人事情報管理データベースのテーブル〕に「索引は主キーだけに定義」とある。
よって、”従業員”テーブルの全ての行を検査する必要があり、これにより処理時間が長くなると考えられる。
したがって、『”従業員”テーブルの”部署コード”に索引がなく、”従業員”テーブルの全行に対して検査を行わなければならないから』となる。
ポイント
<ポイント>
・猶予モードの検査内容→参照制約についての検査
・検査契機モードと挙動モードの関係(検査契機モードは参照制約のタイミングの話で、挙動モードは、更新時の反映の仕方や有無の話?)
<挙動モード;NO ACTION|検査契機モード;猶予モード>
更新時;参照元へ反映しない。検査制約をトランザクション終了時に行う。
<挙動モード;NO ACTION|検査契機モード;即時モード>
更新時;参照元へ反映しない。検査制約を各SQL終了時に行う。
<挙動モード;CASCADE|検査契機モード;猶予モード>
更新時;参照元へ反映する。検査制約をトランザクション終了時に行う。
<挙動モード;CASCADE|検査契機モード;即時モード>
更新時;参照元へ反映する。検査制約を各SQL終了時に行う。
| 組み合わせ | 挙動(データの反映) | 制約検査のタイミング | 主な特徴 |
|---|---|---|---|
| NO ACTION × 即時モード | 反映しない | 各SQL実行後に即検査 | 最も厳格。整合性維持は強いが柔軟性は低い |
| NO ACTION × 猶予モード | 反映しない | トランザクション終了時に検査 | トランザクション内で一時的な不整合を許容 |
| CASCADE × 即時モード | 自動反映する | 各SQL実行後に即検査 | 更新・削除が即時に連鎖反映 |
| CASCADE × 猶予モード | 自動反映する | トランザクション終了時に検査 | 大量更新・バッチ処理向き |




