DDLを仕上げる
作る順番が決まっている
ここまで、テーブルは必要になった順に足してきました。しかし本番環境を新しく立てるときや、テスト用のデータベースを作り直すときには、ゼロから通しで作れる DDL 一式が要ります。
そのとき初めて、順番の問題が出てきます。
CREATE TABLE orders (
store_id integer NOT NULL REFERENCES stores (id)
);
-- ERROR relation "stores" does not exist外部キーは、参照先のテーブルが先に存在していないと書けません。つまり DDL 一式の並び順は、参照の向きによって決まります。
依存を階層で捉える
並べ方は簡単です。誰も参照していないテーブルから始めて、参照している相手が全部そろったものを順に足していきます。
| 段 | テーブル | 参照先 |
|---|---|---|
| 1段目 | prefectures, categories, customers | 無し |
| 2段目 | stores, products | 1段目 |
| 3段目 | product_tags, orders | 2段目 |
| 4段目 | order_items, inventories, shipments | 3段目 |
同じ段の中の順番はどれでも構いません。段の順番だけが決まっている、という捉え方をすると迷いません。
順番を考えたくない場合
外部キーを CREATE TABLE の中に書かず、全テーブルを作ってから ALTER TABLE ... ADD CONSTRAINT でまとめて足す書き方もあります。
| 書き方 | 利点 | 欠点 |
|---|---|---|
| CREATE の中に書く | 定義が1か所にまとまる | 作成順を守る必要がある |
| あとから ALTER で足す | 順番を気にしなくてよい | 定義が2か所に分かれる |
手で書く設計書としては前者が読みやすく、機械が出力する移行スクリプトでは後者がよく使われます。読む相手が人か機械かで選びます。
消す順番は逆になる
作り直すときは削除もします。削除の順番は作成の逆、つまり参照している側からです。
DROP TABLE IF EXISTS order_items;
DROP TABLE IF EXISTS orders;
DROP TABLE IF EXISTS customers;IF EXISTS を付けておくと、まだ無いテーブルを消そうとしてもエラーになりません。何度流しても同じ結果になる、という性質は移行スクリプトで重要です。
手を動かす
1段目の2テーブルだけが用意されています。残りを正しい順番で作り切ります。
テーブル構造
CREATE TABLE prefectures (
pref text PRIMARY KEY,
region text NOT NULL
);
CREATE TABLE categories (
id integer PRIMARY KEY,
name text NOT NULL
);
期待される出力
| table_count | fk_count |
|---|---|
| 10 | 10 |