資格道場 › レッスン一覧 › データベース
データベース・3/13・12分

主キー・外部キーと整合性制約

ゴール

主キー・一意性・参照の各制約について、どの SQL 操作が制約違反になるかを判定できるようになる。外部キーを定義する目的と、データ項目の命名規約では防げない問題も答えられるようになる。

「この操作はエラーになるか」は、表を見て手順どおりに確かめれば必ず正解できるので、確実に取れる得点源です。実務では「存在しない顧客IDの注文が入る」事故をデータベース側で止める仕組みであり、API 設計でいう入力検証をデータベースの層でかけるものと考えると分かりやすいです。

このレッスンで稽古する(用語チェック・過去問)

結論:3つのルールで判定できる

このレッスンの問題は、次の3つのルールで判定できます。

  1. 主キー:値が重複してはいけない。NULL(値が無い状態)も入れられない
  2. 外部キー:外部キーの値は、参照先の表の主キーに実際にある値でなければならない
  3. 命名規約:名前と型はそろえられるが、取り得る値の範囲まではそろえられない

残りは、この3つを表と SQL に当てはめる作業です。

主キー:行を1つに特定するための番号

**主キー(Primary Key)**は、表の中の1行を確実に1つに特定するための列です。社員番号にたとえると、同じ番号の社員が2人いたり、番号が空欄の社員がいたりすると「誰のことか」が決まりません。

主キーの条件 正しいか
値が重複しない(一意) ○ 必須
NULL(空)でない ○ 必須
1列で構成する × 複数列を組み合わせてもよい(複合キー)
表の先頭の列にある × どの位置の列でもよい
検索条件に必ず主キーを指定する × 主キー以外の列でも検索できる
数値型の主キーは計算に使えない × 計算にも使える

試験で正解になるのは「重複しない」「空でない」のどちらかです。「1列だけ」「先頭の列」「計算できない」のような余計な制限が付いた選択肢は誤りです。

制約の種類と SQL での書き方

制約とは、表に入れてよいデータの条件をデータベースに登録し、条件を破る操作をエラーにして止める仕組みです。キーワードと制約名の対応がそのまま出題されます。

制約名 SQL のキーワード 内容
主キー制約(キー制約の一つ) PRIMARY KEY 重複なし+NULLなし
一意性制約(キー制約の一つ) UNIQUE 重複なし。NULLは入れてもよい
非NULL制約 NOT NULL NULLを入れられない
参照制約(参照整合性制約) FOREIGN KEY ~ REFERENCES 外部キーの値が参照先の表に存在しなければならない
検査制約 CHECK 値の条件(例:在庫数 >= 0)
表明 ASSERTION 複数の表にまたがる条件

FOREIGN KEY と REFERENCES の組み合わせは参照制約と覚えます。キー制約(PRIMARY KEY・UNIQUE)や検査制約(CHECK)と取り違えさせる選択肢が出ます。

主キー制約違反の見抜き方:WHERE で何行が選ばれるか

UPDATE 文で主キーの列を書き換える問題では、WHERE の条件に当てはまる行が何行あるかを最初に数えます。2行以上が当てはまるのに主キーを1つの固定値に書き換えると、書き換え後の行どうしで値が重複してエラーになります。

UPDATE の形 結果
主キーを既存の値に書き換える 違反(既存の行と重複)
当てはまる行が2行以上あり、主キーを同じ値に書き換える 違反(書き換えた行どうしで重複)
主キーを NULL に書き換える 違反
当てはまる行が1行で、まだ使われていない値に書き換える OK
主キー以外の列(商品名など)だけを書き換える OK

注意点1:NULL と比較した条件は成り立たない。 在庫数が NULL の行は「在庫数 >= 20」に当てはまらないので、更新の対象になりません。

注意点2:UNIQUE 制約では NULL を含む組は重複とみなされない。 (A, B) の2列に UNIQUE 制約があっても、(AA01, NULL) や (NULL, NULL) の行は追加できます。違反になるのは、NULL を含まない組で値がまったく同じになる場合だけです。

UPDATE 商品 SET 商品番号 = 'S09'WHERE 在庫数 >= 20書き換え前書き換え後商品番号在庫数商品番号在庫数S0130S0225S03NULLS0410S0930S0925S03NULLS0410対象外当てはまる行は2行(S01・S02)→ 両方 S09 になり重複 → 違反S03 は NULL >= 20 が成り立たず対象外
WHERE に当てはまる2行の主キーを同じ S09 に書き換えると、書き換えた行どうしで重複して違反になる。在庫数が NULL の行は条件に当てはまらず更新されない。

外部キー:他の表の主キーを指す列

**外部キー(Foreign Key)**は、他の表の主キーの値を持つことで、2つの表の行を結び付ける列です。会員番号を書いて予約する仕組みにたとえると、会員名簿に載っていない番号での予約は受け付けない、というルールに当たります。

外部キーを定義する目的は「表と表のあいだで参照の一貫性(参照整合性)を保つ」ことだけです。次の選択肢はどれも外部キーの目的ではありません。

ひっかけの選択肢 実際は何の話か
関係する表を近くに格納して検索を速くする 物理的な格納設計の話
壊れたレコードを表どうしの関係から復旧する 障害回復(ログ・バックアップ)の話
削除と追加の繰り返しによる虫食い状態(フラグメンテーション)を防ぐ 格納領域の再編成の話

用語を整理します。参照する側の表(例:注文)を子表、参照される側の表(例:顧客)を親表と呼びます。

子表:注文親表:顧客参照する側参照される側注文番号顧客番号顧客番号顧客名O1C1O2C2O3C1C1佐藤C2鈴木↑ 外部キー↑ 主キー外部キーの値は親表の主キーにある値だけ
子表(注文)の外部キー「顧客番号」は、親表(顧客)の主キー「顧客番号」にある値を指して2つの表の行を結び付ける。

どの操作が参照整合性を壊すか

判定の基準は、操作した後に、親表に存在しない値を指している子表の行ができるかどうかです。

操作 結果
子表に行を追加:外部キーの値が親表にある OK
子表に行を追加:外部キーの値が親表にない 違反
子表の行を削除 OK(参照している行が消えるだけ)
親表の行を削除:子表から参照されていない行 OK
親表の行を削除:子表から参照されている行 違反(子表の行の参照先が無くなる)
親表に行を追加 OK

データを新しく入れるときは、参照される側(親表)から先に入れます。表が3つ以上つながっているときは、参照の矢印を逆向きにたどった順番が入力の順番になります。

flowchart LR
  A["資産(建物番号と部屋番号で部屋を参照)"] -->|"参照"| B["部屋(建物番号で建物を参照)"]
  B -->|"参照"| C["建物"]

入力の順番は、矢印の終点から始めて 建物 → 部屋 → 資産 です。

① 子表に C9 の注文を追加注文(子表)顧客(親表)O4C9C1C2×親表に C9 が無い → 違反② 親表から C1 を削除O1C1O3C1C1C2O1・O3 の参照先が無くなる → 違反判定:親表に無い値を指す行ができるか
違反になるのは、操作の後に親表に存在しない値を指す子表の行ができるとき。親表に無い C9 の追加も、参照されている C1 の削除も、行き先の無い参照を生む。

データ項目の命名規約:防げることと防げないこと

命名規約とは、データ項目の名前の付け方を統一するルールです。区分語(例:「〜金額」は数値型、「〜年月日」は日付型、と決める語)を名前の末尾に付けるルールと、項目名と意味を登録した辞書で、名前と型の不統一を防ぎます。ただし、**取り得る値の範囲(ドメイン・定義域)**は名前からは決まらないので、命名規約だけではそろえられません。

起きる問題 命名規約で防げるか 防ぐ仕組み
同じ「〜年月日」に日付型と文字列型が混在する ○ 区分語ごとに型を決める
「賞与金額」と「ボーナス金額」が同じ意味で並存する(異音同義語) ○ 辞書に登録して統一する
「取引先」がコードなのか名前なのか分からない ○ 区分語を必ず付ける
「受注金額」の取り得る値の範囲が表によって違う × ドメインの定義や検査制約が必要

「規約の(1)(2)で防げるものはどれか」を1つずつ消していき、最後に残る値の範囲が正解です。

試験での問われ方

  • 主キーの性質:「重複しない」「空でない」が正解です。「1列だけ」「先頭の列」「検索に必須」「計算できない」は誤りです。
  • 制約違反の判定:4つの SQL 文から1つ選ぶ形式です。WHERE に当てはまる行を数え、書き換え後の主キーが重複しないか、NULL にならないかを確かめます。
  • SQL のキーワード:FOREIGN KEY と REFERENCES は参照制約です。
  • 外部キーの目的:高速化・障害復旧・虫食い防止を混ぜた選択肢の中から、参照の一貫性を選びます。
  • 参照整合性の判定:親表に無い値を子表に追加する操作が違反です。親表から先に入力します。
  • 命名規約:防げないのは値の範囲(ドメイン)です。
例題 1

UPDATE で主キーが重複するかを判定する

次の SQL 文によって定義され,値が格納されている“商品”表に対して,制約違反で実行エラーとなる SQL 文はどれか。 〔SQL 文〕 CREATE TABLE 商品 (商品コード CHAR(4) PRIMARY KEY, 商品名 VARCHAR(21), 仕入先コード CHAR(4), 仕入単価 INT, 在庫数 INT)
商品
商品コード商品名仕入先コード仕入単価在庫数
A111テレビS00175,0000
A222デジタルカメラS00250,00050
A333DVDプレーヤNULLNULLNULL
A444洗濯機S00445,00020

ア DELETE FROM 商品 WHERE 仕入先コード IS NULL
イ INSERT INTO 商品 VALUES ('A555', '空気清浄機', 'S005', 60000, 50)
ウ UPDATE 商品 SET 商品コード = 'A666' WHERE 商品コード = 'A444'
エ UPDATE 商品 SET 商品コード = 'A777' WHERE 在庫数 >= 20

出典:令和8年度 基本情報技術者試験 科目A 公開問題 問7

解き方と答えを見る
  1. 主キーを確認する:PRIMARY KEY が付いているのは商品コード。値の重複と NULL が禁止される
  2. ア:仕入先コードが NULL の行は A333 の1行だけ。削除は主キーの重複を生まないので OK
  3. イ:A555 は表にまだ無い値なので、追加しても重複しない。OK
  4. ウ:WHERE 商品コード = 'A444' に当てはまるのは1行だけ。A666 は表に無い値なので OK
  5. エ:在庫数 >= 20 に当てはまる行を数える。A111 は0なので対象外、A222 は50なので対象、A333 は NULL なので条件が成り立たず対象外、A444 は20なので対象 → 当てはまるのは2行
  6. この2行の商品コードをどちらも 'A777' にすると、A777 の行が2行になって主キーが重複する → 制約違反

答え:エ(2行が同じ主キー 'A777' になるため実行エラーになる)

例題 2

参照整合性を損なう操作を見つける

関係データベースの “注文” 表の “顧客番号” は,“顧客” 表の主キー “顧客番号” を参照する外部キーである。このとき,参照の整合性を損なうデータ操作はどれか。ここで,ア~エの記述におけるデータの並びは,それぞれの表の列の並びと同順とする。
注文表:
伝票番号顧客番号
0001C005
0002K001
0003C005
0004D010
顧客表:
顧客番号顧客名
C005福島
D010千葉
K001長野
L035宮崎

ア “顧客” 表の行 [L035 | 宮崎] を削除する。
イ “注文” 表に行 [0005 | D010] を追加する。
ウ “注文” 表に行 [0006 | F020] を追加する。
エ “注文” 表の行 [0002 | K001] を削除する。

出典:平成24年度 秋期 基本情報技術者試験 午前 問31

解き方と答えを見る
  1. 子表は注文(外部キーは顧客番号)、親表は顧客(主キーは顧客番号)と確認する
  2. 親表にある顧客番号を書き出す:C005, D010, K001, L035
  3. ア:親表の L035 を削除する。注文表に L035 を参照している行は無いので OK
  4. イ:注文表に D010 の行を追加する。D010 は親表にあるので OK
  5. ウ:注文表に F020 の行を追加する。F020 は親表に無いので、存在しない顧客を指す注文になる → 違反
  6. エ:子表(注文)の行を削除する。参照している側が消えるだけなので OK

答え:ウ(顧客表に存在しない F020 を外部キーに入れることになる)

例題 3

参照関係から入力の順番を決める

事務室が複数の建物に分散している会社で,PC の設置場所を管理するデータベースを作ることになった。“資産”,“部屋”,“建物”の三つの表を作成し,各表の関連付けを行った。新規にデータを入力する場合は,参照される表のデータが先に存在している必要がある。各表へのデータの入力順序として,適切なものはどれか。ここで,各表の下線部の項目は,主キー又は外部キーである。
資産: | PC番号 | 建物番号 | 部屋番号 | 機種名 |(PC番号,建物番号,部屋番号に下線) 部屋: | 建物番号 | 部屋番号 | 部屋名 |(建物番号,部屋番号に下線) 建物: | 建物番号 | 建物名 |(建物番号に下線)

ア 資産 → 建物 → 部屋
イ 建物 → 部屋 → 資産
ウ 部屋 → 資産 → 建物
エ 部屋 → 建物 → 資産

出典:基本情報技術者試験 科目A免除 修了試験 20230122 実施分 問25

解き方と答えを見る
  1. 参照の向きを書き出す:資産は(建物番号、部屋番号)で部屋を参照する。部屋は建物番号で建物を参照する
  2. 参照の矢印をつなげる:資産 → 部屋 → 建物
  3. 参照される側を先に入力するというルールなので、矢印の終点から逆にたどる
  4. 建物(どの表も参照していない)→ 部屋(建物があれば入力できる)→ 資産(部屋があれば入力できる)

答え:イ(建物 → 部屋 → 資産)

要点(試験直前に読む)

  • 主キーは「重複なし+NULLなし」。複数列で作ってもよく、表の先頭の列である必要もない
  • UPDATE で主キーを書き換える問題は、WHERE に当てはまる行を数える。2行以上を同じ値にすると違反になる。NULL の行は比較条件に当てはまらない
  • UNIQUE 制約は NULL を入れられ、NULL を含む組は重複とみなされない
  • FOREIGN KEY と REFERENCES で指定するのは参照制約。目的は表と表のあいだの参照の一貫性を保つこと
  • 親表に無い値を子表に追加すると違反。新しく入力するときは親表から先に入れる
  • 命名規約で防げるのは型の混在・同義語・区分語の付け忘れ。値の範囲(ドメイン)は防げない

ひっかけ

  • 「主キーは1列」「先頭の列」「計算できない」のように余計な制限が付いた選択肢は誤り。正解は「重複しない」「空でない」
  • UPDATE の WHERE が主キー以外の列(在庫数・商品名など)だと、当てはまる行が複数になりやすい。主キーの列を1つの値に書き換える文を見たら、当てはまる行数を必ず数える
  • NULL を含む行の INSERT を UNIQUE 制約違反だと思い込ませる。NULL を含む組は重複とみなされない
  • 外部キーの目的として、高速化・障害復旧・虫食い防止を混ぜてくる。正解は参照の一貫性だけ
  • 子表の削除や、参照されていない親表の行の削除は問題ない。違反になるのは、親表に無い値を子表に追加する操作と、参照されている親表の行の削除

用語(14)

主キー しゅきー(Primary Key)
表の中の1行を1つに特定するための列(または列の組み合わせ)で、値の重複と NULL が許されない。
⚠ 一意性制約(UNIQUE)とは、NULL を入れられない点が違う。
複合キー ふくごうきー
2つ以上の列を組み合わせて作るキー。
⚠ 「主キーは1列でなければならない」は誤り。複合キーを主キーにしてよい。
候補キー こうほきー
行を1つに特定できる最小限の列の組で、主キーにできる候補になるもの。
⚠ 候補キーの中から1つ選んだものが主キー。
NULL ナル
値が入っていない・決まっていないことを表す特別な状態。
⚠ 0 や空文字とは別物。NULL との比較(>= など)は成り立たないので、WHERE の条件に当てはまらない。
一意性制約 いちいせいせいやく(UNIQUE)
指定した列(または列の組)の値が重複しないことを保証する制約。
⚠ 主キー制約と違って NULL を入れられ、NULL を含む組は重複とみなされない。
主キー制約 しゅきーせいやく(PRIMARY KEY)
主キー列について、値が重複しないことと NULL でないことを保証する制約。
⚠ 一意性制約と合わせて「キー制約」と呼ぶ。参照制約とは別。
外部キー がいぶきー(Foreign Key)
他の表の主キーの値を持ち、その表の行を参照する列。
⚠ 主キーと違い、外部キーは同じ値が何度出てきてもよい。
参照制約 さんしょうせいやく(参照整合性制約)
外部キーの値が、参照先の表の主キーに存在することを保証する制約で、FOREIGN KEY と REFERENCES で指定する。
⚠ キー制約(PRIMARY KEY・UNIQUE)や検査制約(CHECK)と、SQL のキーワードで見分ける。
参照整合性 さんしょうせいごうせい
子表の外部キーが、親表に存在する行だけを指している状態。
⚠ 外部キーの目的はこれだけ。高速化・障害復旧・虫食い防止は無関係。
検査制約 けんさせいやく(CHECK)
列の値が指定した条件(範囲など)を満たすことを保証する制約。
⚠ 参照制約は他の表との関係を見るが、検査制約は自分の表の値の条件だけを見る。
表明 ひょうめい(ASSERTION)
複数の表にまたがる条件をデータベース全体の制約として宣言するもの。
⚠ 1つの表の値の条件を定める検査制約と区別する。
親表・子表 おやひょう・こひょう
参照される側の表を親表、外部キーを持って参照する側の表を子表と呼ぶ。
⚠ 新しく入力するのは親表が先。削除で問題になるのは、参照されている親表の行。
ドメイン ドメイン(定義域)
あるデータ項目が取り得る値の範囲や種類。
⚠ データ型(数値型・日付型など)とは別。命名規約で型はそろえられるが、ドメインはそろえられない。
異音同義語・同音異義語 いおんどうぎご・どうおんいぎご
異音同義語は名前が違うのに意味が同じ項目、同音異義語は名前が同じなのに意味が違う項目。
⚠ どちらも項目名と意味を登録した辞書で防げる。命名規約で防げないのは値の範囲。

このレッスンの過去問

このレッスンで稽古する