3秒でわかる
多重度とは、UMLのクラス図などで、一方の要素1個に対して相手が何個結びつけるかを示す数の範囲です。1はちょうど1個、0..1は0か1個、1..*は1個以上を表します。
30秒図解
もう少し詳しく
多重度の記号一覧
まずは、線の端に書かれた記号をそのまま読めるようにします。
| 記号 | 意味 | 0個を許すか |
|---|---|---|
1 | ちょうど1個 | 許さない |
0..1 | 0個または1個 | 許す |
0..* または * | 0個以上 | 許す |
1..* | 1個以上 | 許さない |
2..5 | 2個以上5個以下 | 許さない |
.. は最小値と最大値の範囲、* は上限なしを表します。
多重度「1」とは
検索で特に迷いやすい 1 は、「最大1個」ではなく必ずちょうど1個です。0個を許すなら 0..1 と書きます。
たとえば注文明細側から注文側を見た端に 1 があれば、「どの注文明細も、必ず1件の注文に属する」という意味です。注文が決まっていない注文明細は存在できません。
線は両方向から読む
「注文」と「注文明細」の関係を、次のように書いたとします。
注文 1 ───────── 1..* 注文明細同じ線を、反対向きの2つの質問に分けて読みます。
1..* なので1件以上1 なのでちょうど1件端にある数字は、反対側の1個から見て、この側が何個あるかを表します。数字のすぐ隣の箱から読み始めると向きを逆にしやすいため、「反対側から質問する」と覚えるのが安全です。
UMLとER図では記法が違う
UMLのクラス図では 0..1 や 1..* のような数の範囲を線の端に書きます。ER図では 1 と N、丸と線とカラスの足などを使う記法もあります。
見た目は違っても、どちらも「最小で何個、最大で何個結びつくか」という業務ルールを表します。ER図ではこの関係をカーディナリティと呼ぶこともあります。
多重度がデータベース設計を決める
多重度は図の飾りではなく、テーブルの形へ直結します。
| 関係 | よく使う実装 |
|---|---|
| 1対多 | 多の側に外部キーを持たせる |
| 0または1対1 | 外部キーを NULL 許容にし、必要なら UNIQUE を付ける |
| 必ず1対1 | 外部キーを NOT NULL かつ UNIQUE にする |
| 多対多 | 2つの外部キーを持つ中間テーブルを作る |
ただし、親1件に子が最低1件必要という 1..* の最小値は、子テーブルの外部キーを NOT NULL にするだけでは保証できません。NOT NULL が保証するのは「子が親なしにならない」ことです。「親に子が1件以上ある」ことは、登録処理を同じトランザクションにする、制約用の処理を用意するなど別の設計が必要です。
具体例 多対多をテーブルへ直す
「学生は複数の講義を履修でき、講義には複数の学生が参加できる」は多対多です。RDBでは中間テーブルへ分解します。
CREATE TABLE students (
id BIGINT PRIMARY KEY,
name VARCHAR(100) NOT NULL
);
CREATE TABLE courses (
id BIGINT PRIMARY KEY,
title VARCHAR(200) NOT NULL
);
CREATE TABLE enrollments (
student_id BIGINT NOT NULL,
course_id BIGINT NOT NULL,
PRIMARY KEY (student_id, course_id),
FOREIGN KEY (student_id) REFERENCES students(id),
FOREIGN KEY (course_id) REFERENCES courses(id)
);学生と履修の1対多、講義と履修の1対多という2本の関係に分けることで、多対多を表現できます。
つまずきやすいところ
1 を「1個まで」と読む。正しくは「必ず1個」で、任意なら 0..1 です* と 1..* を同じだと思う。* は 0..* の省略形なので0個を許しますよくある質問
多重度とカーディナリティは同じですか
関係の「何対何」を表す場面では、ほぼ同じ意味で使われます。ただしデータベースの性能の話でいうカーディナリティは、列に異なる値が何種類あるかを指すこともあります。周囲が設計図の話か、インデックスや統計情報の話かで見分けます。
0..* と * は違いますか
UMLでは * は 0..* の省略形で、どちらも0個以上です。最低1個が必要なら 1..* と書きます。
上限だけを決めることもできますか
できます。たとえばチームのメンバーを最大5人にするなら 0..5、必ず2人以上5人以下なら 2..5 と書けます。実装でその上限をどこに持たせるかは別途決めます。
覚え方
1 は必ず1個、* は上限なし、.. は最小と最大の範囲。読む向きは「反対側の1個から、この側はいくつ」です。