ER図の記法
表と表のあいだに線を引く
第1章で5つのテーブルを作りました。しかしいまの状態では、orders の store_id に 999 を入れても誰も止めません。存在しない店舗の注文が生まれてしまいます。
エンティティ同士がどう繋がっているのかを図にしたものがER図です。E は Entity、R は Relationship の頭文字です。
mermaid で書く
ER図は手描きでも構いませんが、テキストで書けると差分が追えるので便利です。ここでは mermaid という記法を使います。
erDiagram
stores ||--o{ inventories : has
products ||--o{ inventories : stocked_as真ん中の記号が関係の形を表します。左から順に読みます。
| 記号 | 意味 |
|---|---|
| ` | |
o{ | 0以上 |
| ` | {` |
| `o | ` |
stores ||--o{ inventories は「1つの店舗に対して、在庫の行は0件以上ある」と読みます。逆から読めば「1件の在庫は、必ずちょうど1つの店舗に属する」です。
線を DDL にする
この線を実際のデータベースで表すのが外部キーです。
CREATE TABLE inventories (
store_id integer NOT NULL,
product_id integer NOT NULL,
quantity integer NOT NULL,
PRIMARY KEY (store_id, product_id),
CONSTRAINT inventories_store_fk FOREIGN KEY (store_id) REFERENCES stores (id),
CONSTRAINT inventories_product_fk FOREIGN KEY (product_id) REFERENCES products (id)
);FOREIGN KEY (store_id) REFERENCES stores (id) は「この列の値は stores の id に必ず存在する」という約束です。存在しない番号を入れようとすると、データベースがその挿入を拒否します。
制約に名前を付ける
CONSTRAINT inventories_store_fk の部分は省略できます。省略するとデータベースが inventories_store_id_fkey のような名前を勝手に付けます。
しかし自分で名前を付けたほうがよいです。エラーメッセージに出るのは制約名なので、inventories_store_fk と出れば何が起きたのか一目で分かります。名前は <テーブル名>_<列の意味>_fk の形で揃えます。
図と実装は一致していないと意味がない
ER図はドキュメントなので、更新を忘れると簡単に嘘になります。だから図を描いたら必ずその場で DDL に落として動かす、という順番を習慣にします。動くものと図が同時に生まれれば、ずれようがありません。
手を動かす
上の ER図をそのまま inventories の DDL にして、制約が本当に付いたかをデータベースに聞きます。
テーブル構造
CREATE TABLE stores (
id integer PRIMARY KEY,
name text NOT NULL,
pref text NOT NULL,
opened_on date
);
CREATE TABLE products (
id integer PRIMARY KEY,
name text NOT NULL,
price integer NOT NULL,
category text NOT NULL,
is_active boolean NOT NULL
);
期待される出力
| constraint_type | cnt |
|---|---|
| FOREIGN KEY | 2 |
| PRIMARY KEY | 1 |