ER図の記法

表と表のあいだに線を引く

第1章で5つのテーブルを作りました。しかしいまの状態では、ordersstore_id999 を入れても誰も止めません。存在しない店舗の注文が生まれてしまいます。

エンティティ同士がどう繋がっているのかを図にしたものが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) は「この列の値は storesid に必ず存在する」という約束です。存在しない番号を入れようとすると、データベースがその挿入を拒否します。

制約に名前を付ける

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_typecnt
FOREIGN KEY2
PRIMARY KEY1

ヒント

query.sql
学習モード
コードの実行結果
データベースを初期化中...