やあ。今日はPostgreSQLの第一歩、`CREATE TABLE`の話をしようか。
「テーブルを作るくらい、チュートリアルを見れば誰でもできるよ」って思うかもしれない。でもね、実務で使うテーブルは、ただデータが入ればいいってもんじゃないんだ。設計の段階でどれだけ「未来の自分」を助けられるか。それが、優秀なエンジニアとそうでないエンジニアの分かれ道だったりする。
今日は、教科書には載っていない「現場の肌感覚」を交えて、PostgreSQLでテーブルを定義するときのツボを解説するよ。
—
1. 基本の型選びと「NOT NULL」の重要性
まず、基本の構文を見てみよう。
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
ここで一番伝えたいのは、「迷ったら `NOT NULL` をつける」という鉄則だ。
初心者はつい「とりあえずNULL許容にしておこう」としがちなんだけど、これは後で必ず泣きを見る。アプリケーション側で「値が入っていないケース」を考慮するコードを書くのがどれだけ面倒か、一度経験すると痛いほど分かるはずだ。データに一貫性を持たせることこそ、RDBMSを使う最大のメリットなんだからね。
2. データ型選びの「ちょっとしたこだわり」
次に、データ型について。
- `VARCHAR(n)` vs `TEXT`: PostgreSQLにおいて、`VARCHAR(n)`と`TEXT`のパフォーマンス差はほとんどない。じゃあなぜ`VARCHAR(50)`と書くのか? それは「この項目は最大でもこれくらいの長さであるべき」という、テーブル定義そのものがドキュメントとしての役割を持つからだ。
- `TIMESTAMP WITH TIME ZONE`: これ、非常に重要。DBの時刻を扱うときは、必ずタイムゾーン付きを使うクセをつけておこう。将来的に海外展開したり、サーバーの時刻設定が変わったりしたとき、こいつが君を地獄から救ってくれる。
3. 制約(Constraints)は「データの守護神」
制約は、単なるルールじゃない。DBというシステムが君たちの代わりにデータを守ってくれる「守護神」だ。
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
price INT CHECK (price >= 0),
status VARCHAR(20) DEFAULT ‘pending’
);
特に注目してほしいのが `CHECK` 制約だ。「価格がマイナスになるわけがない」といったビジネスロジックに近い制約をDB側でかけておくと、バグったプログラムが誤ったデータを流し込もうとしても、PostgreSQLが「おい、それはおかしいだろ」と門前払いしてくれる。これがあるだけで、深夜の障害対応の確率がグッと下がるよ。
4. デフォルト値の使いこなし
`DEFAULT CURRENT_TIMESTAMP` は定番だよね。でも、たまに「アプリケーション側で全部管理するからいいや」というプロジェクトに出会う。
僕のアドバイスとしては、「作成日時」のようなメタデータは、極力DBのデフォルト値に任せるのがおすすめだ。アプリケーションの言語が変わっても、フレームワークが変わっても、DB自体が正しく時間を記録してくれる。この「疎結合」な考え方は、長く運用するシステムほど真価を発揮するよ。
—
先輩から最後にひとこと
テーブル作成は、家でいう「基礎工事」だ。後から変えようと思うと、テーブルの再構築やデータの移行といった、非常にコストのかかる作業が発生する。
だからこそ、最初の `CREATE TABLE` を書くとき、少しだけ立ち止まって考えてみてほしい。
「このカラムは本当に空でもいいのか?」
「この値の範囲はどこまでか?」
「将来、このデータはどれくらい増えるのか?」
そうやって一つずつ丁寧に定義したテーブルは、数年経っても君を裏切らない、最高の相棒になってくれるはずだ。
さて、次は `INDEX` の話をしようか。テーブルができたら、次は「いかに速くデータを引くか」が重要になる。また次の記事で会おう。ハッピー・コーディング!
コメント