「型」を制するものは、PostgreSQLを制する。
現場でバリバリコードを書いていると、つい「とりあえず `VARCHAR` でいいか」「ステータスは `INTEGER` で持っておいて、アプリ側で管理しよう」と妥協したくなる気持ち、よくわかります。でも、ちょっと待ってほしい。
データベースの設計において、「型」は最強のドキュメントであり、最強の防御壁です。今回は、PostgreSQLが誇る強力な武器、「カスタム型(DomainとEnum)」について、実戦的な話をしようと思います。
—
1. CREATE DOMAIN:型に「意志」を持たせる
`DOMAIN` は、既存の型に制約(CHECK制約など)をあらかじめ組み込んで、新しい型として定義できる機能です。
例えば、「メールアドレス」や「電話番号」のように、アプリ全体で同じバリデーションを何度も書くのは、DRY原則に反するし、何よりバグの温床ですよね。
— メアド用の型を作る例
CREATE DOMAIN email_address AS TEXT
CHECK (VALUE ~ ‘^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$’);
— テーブル定義で使う
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email email_address NOT NULL
);
なぜこれが「現場」で刺さるのか?
単に `CHECK` 制約をテーブルに書くだけでもいい。でも、`DOMAIN` を作っておけば、「このカラムにはメールアドレスが入る」という意図が型名としてコードに残り、しかも全テーブルで同じ制約を使い回せるんです。
もし将来、「メアドのバリデーションをもう少し厳しくしたい」となったとき、テーブルごとに `ALTER TABLE` を叩く必要はありません。`DOMAIN` を更新すれば、それに依存する全てのカラムに一括で適用できる。これぞデータベース設計の醍醐味です。
—
2. CREATE TYPE (ENUM):魔法の「選択肢」
次に `ENUM` です。ステータス管理で `1: 受付中, 2: 処理中, 3: 完了` みたいに整数値を使っているなら、今すぐやめましょう。SQLを叩くたびに「これなんだっけ?」とドキュメントを見に行く苦行はもう終わりにしませんか?
— Enum型を作る
CREATE TYPE order_status AS ENUM (‘pending’, ‘processing’, ‘completed’, ‘cancelled’);
— カラムに使う
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
status order_status DEFAULT ‘pending’
);
現場の先輩からのアドバイス:Enumの「落とし穴」
`ENUM` は直感的で素晴らしいんですが、実務で使うなら必ず知っておくべき注意点があります。
- 変更に弱い: 例えば、`ENUM` に新しい選択肢を追加するのは簡単ですが、途中に挿入したり削除したりするのは、データベースの構造上少し面倒です。
- 柔軟性: 「将来的に選択肢が無限に増えるかも?」というもの(例えば『カテゴリ』など)には向きません。そういう場合は、素直にマスタテーブルを作るのが正解です。
結論: 「ステータス」や「ロール」のように、開発中にほぼ確定していて、かつ変更頻度が極めて低いものに使うのが最強です。
—
3. 結局、使い分けはどうするの?
ここまで読んで「じゃあ結局、何を使えばいいの?」と思ったあなた。基準はシンプルです。
1. バリデーションを共通化したい → `DOMAIN` を使う。
2. 値の種類が限定的で、コードの可読性を上げたい → `ENUM` を使う。
3. データが変動する可能性がある → 潔くテーブル(マスタ)を切る。
データベース設計は、パズルのようなものです。型を適切に定義してやるだけで、アプリケーション側のバリデーションコードは驚くほど減り、データの整合性は飛躍的に高まります。
—
最後に:型は裏切らない
システム開発で一番怖いのは「想定外のデータ」が紛れ込むことです。プログラム側でどれだけガードしても、誰かが直接SQLで `UPDATE` を叩いた瞬間にデータは汚染されます。
データベース自身に「この型はこうあるべきだ」という制約を持たせておくこと。これが、僕らDBエンジニアができる、最もコストパフォーマンスの良い「自己防衛」なんです。
まずは小さなところから、`DOMAIN` や `ENUM` を使ってみてください。コードを書き終えたとき、きっと「あ、この設計、堅牢で美しいな」とニヤリとできるはずですよ。
それでは、良いDBライフを!
コメント