ALTER TABLE で構造を変更する

ALTER TABLE で構造を変更する とは

ALTER TABLEを使ってテーブルの構造を変更する方法を学びます。カラムの追加や変更を実践!。本レッスンでは、ALTER TABLE で構造を変更する の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

なぜ重要か

プロダクトが成長するにつれ、テーブル設計は必ず変化を求められます。新しい列を追加したい、既存列の型を変えたい、要らなくなった列を削除したい、こうした「すでに動いているテーブルの形を変える」命令が ALTER TABLE です。アプリ開発者にとっては「マイグレーションを書く」という言葉で日常的に出会う命令でもあります。大規模なテーブルで何も考えずに ALTER を流すと、テーブルが長時間ロックされて全リクエストが詰まる事故になります。ALTER は「動いている車のエンジンを交換する」のに近い操作で、必要性と運用上のリスクの両方を理解しておく必要があります。

主なバリエーション

SQL クエリ

-- 列を追加 ALTER TABLE users ADD COLUMN phone VARCHAR(20); -- 列を削除 ALTER TABLE users DROP COLUMN phone; -- 列の型を変える ALTER TABLE users ALTER COLUMN age TYPE BIGINT; -- 列名を変える ALTER TABLE users RENAME COLUMN name TO display_name; -- NOT NULL 制約を追加する ALTER TABLE users ALTER COLUMN display_name SET NOT NULL; -- インデックスを追加 CREATE INDEX idx_users_email ON users (email);

列追加の流れ

diagram (will load when visible)

NOT NULL の列を追加する場合は、既存行が無いか、または DEFAULT を必ず指定します。大量の既存データに DEFAULT を流し込むと書き込み量が大きくなり、本番では「2 段階デプロイ」 (まず NULL 許容で追加 → アプリで値を埋める → NOT NULL 化) という運用がよく使われます。

代表例 — 顧客テーブルに会員ランク列を追加

SQL クエリ

-- 既存テーブルがあるとする -- CREATE TABLE customers (id INT PRIMARY KEY, name VARCHAR(100)); -- 1. ランク列を追加 (NULL 許容で気軽に追加) ALTER TABLE customers ADD COLUMN rank VARCHAR(20); -- 2. 既存データに値を埋める UPDATE customers SET rank = 'bronze' WHERE rank IS NULL; -- 3. NOT NULL 化して締める ALTER TABLE customers ALTER COLUMN rank SET NOT NULL;

3 段階に分けることで、本番ロックを最小化できます。

列を消す前に必ず確認

本番で列を消すと、その列を参照しているクエリが一斉に壊れます。

SQL クエリ

-- アプリのコードと SQL を grep して参照ゼロを確認してから ALTER TABLE customers DROP COLUMN legacy_flag;

注意 ALTER TABLE は「すぐ終わる軽い操作」と思いがちですが、PostgreSQL でも操作内容によってはテーブル全行の検証や書き換えが発生する重い処理になります。1000 万行のテーブルに ALTER を流して 30 分ロック、というのは現場でよく起こります。本番では ONLINE オプションや pt-online-schema-change などの仕組みを検討します。

アプリの世界では ALTER TABLE を生で書くより、drizzle-kitprisma migrate のようなマイグレーションツール経由で生成・適用するのが主流です。ツールが自動生成する SQL をレビューできる目を持つことが、結局のところ ALTER TABLE を読み書きできることに繋がります。

本番マイグレーションで列を「リネーム」したい時は、直接 RENAME COLUMN で名前を変えない方が安全です。理由は「旧列で動いている古いアプリと、新列を期待する新しいアプリ」が同時に走るタイミングがあるからです。代わりに、新列を追加 → 両方に書く → 旧列の参照を消す → 旧列を消す、という 4 段階のデプロイが鉄則です。

インデックス追加と削除

インデックスも ALTER TABLE で足したり消したりできます。

SQL クエリ

-- email に検索高速化用のインデックスを追加 CREATE INDEX idx_users_email ON users (email); -- 使われていないインデックスを削除 DROP INDEX idx_users_email;

インデックスの細かい話は最終章で扱いますが、ALTER の構文の一部として頭に入れておくと、本番のマイグレーションログを読めるようになります。

まとめ

  • ADD / DROP / ALTER COLUMN / RENAME COLUMN / CREATE INDEX が構造変更の主な顔ぶれ
  • 列追加は NULL 許容 → データ埋め → NOT NULL 化の 3 段階が安全
  • 列削除はアプリ参照ゼロを確認してから
  • リネームは「新列追加 → 両書き → 旧列消し」の 4 段階デプロイ
  • 本番大規模テーブルは長時間ロックの可能性、ONLINE 系の仕組みを検討する

次のレッスン

次は 制約 (NOT NULL / UNIQUE / DEFAULT) です。NOT NULL、UNIQUE、DEFAULT制約をSQLで設定する方法を実践的に学びます。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. ALTER TABLE の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. ALTER TABLE とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

テーブル構造

schema.sql

CREATE TABLE customers ( id INT PRIMARY KEY, name VARCHAR(100) NOT NULL ); INSERT INTO customers (id, name) VALUES (1, '田中太郎'), (2, '佐藤花子'), (3, '山田次郎');

期待される出力

idnamemember_rank
1田中太郎bronze
2佐藤花子bronze
3山田次郎bronze

ヒント

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