4.

SQL ALTER TABLE DROP COLUMNでカラム削除|DBMS別の差と依存対処

編集
この記事の要点
  • テーブルから列(カラム)を削除するには ALTER TABLE 表名 DROP COLUMN 列名
  • MySQL / PostgreSQL では COLUMN キーワードは省略可、Oracle では一部省略不可
  • 制約・インデックス・外部キー・トリガーが参照している列はそのままでは削除できないことが多い
  • 本番運用では 論理削除 → 非利用化 → 物理削除 の二段階で進めるとロールバックが容易
  • 大規模テーブルでは ALGORITHM=INSTANT(MySQL 8)などオンライン DDL 対応の構文を選ぶ

はじめに

テーブルの列(カラム)が不要になったとき、ALTER TABLE 文の DROP COLUMN 句で削除できます。シンプルに見えますが、外部キーやインデックス、トリガーから参照されていたり、巨大なテーブルだとロック・ダウンタイムの問題が出たりするため、実運用では注意点が多くあります。

基本構文

ALTER TABLE 表名 DROP COLUMN 列名;

基本例

-- employees テーブルから middle_name 列を削除
ALTER TABLE employees DROP COLUMN middle_name;

DBMS 別の差

DBMS構文備考
OracleALTER TABLE 表 DROP COLUMN 列;DROP (col1, col2) で複数列。SET UNUSED で論理削除も可能
MySQL / MariaDBALTER TABLE 表 DROP COLUMN 列; / ALTER TABLE 表 DROP 列;COLUMN 省略可。MySQL 8 は INSTANT アルゴリズムで瞬時削除可能な場合あり
PostgreSQLALTER TABLE 表 DROP COLUMN 列 [IF EXISTS] [CASCADE];CASCADE で依存も一緒に削除可
SQL ServerALTER TABLE 表 DROP COLUMN 列;依存制約・インデックスは事前削除が必要
SQLite3.35.0 以降で ALTER TABLE 表 DROP COLUMN 列;古いバージョンは「テーブル再作成」が必要

複数カラムを一度に削除

Oracle

ALTER TABLE employees DROP (middle_name, nickname);

MySQL / PostgreSQL

ALTER TABLE employees
    DROP COLUMN middle_name,
    DROP COLUMN nickname;

SQL Server

ALTER TABLE employees
    DROP COLUMN middle_name, nickname;

依存オブジェクトのチェック

削除しようとした列に次のような依存があると、エラーで止まるか、CASCADE 指定が必要になります。

依存挙動
NOT NULL / UNIQUE / CHECK 制約列削除と同時に消えることが多い
主キー主キー全体を DROP CONSTRAINT してから列削除
外部キー(自テーブル側)外部キーを先に DROP CONSTRAINT
外部キー(他テーブルから参照されている)参照側を直してから / CASCADE で一緒に削除
インデックス列削除と一緒に消える(複合インデックスは一部のみだと挙動が変わる)
ビュー・マテビュー使用列を含むビューは無効化される
トリガー・関数本文中で参照していた場合、実行時にエラー

論理削除 → 物理削除のステップ

本番テーブルで列をいきなり物理削除すると、アプリ側で参照していた SQL が一斉に失敗するリスクがあります。次のステップで進めると安全です。

  1. アプリから書き込み停止: INSERT/UPDATE で当該列を使うコードを外す
  2. 読み取りも停止: SELECT * を含めて参照箇所を排除
  3. 論理削除フェーズ: Oracle なら ALTER TABLE 表 SET UNUSED (列)、他 DBMS なら列にコメントを付け運用ドキュメントで「未使用」と宣言
  4. 本番待機期間: 1〜2 リリースサイクル放置して問題なければ次へ
  5. 物理削除: ALTER TABLE 表 DROP COLUMN 列

大規模テーブルの注意

DBMSヒント
MySQL 8多くの DROP COLUMN は ALGORITHM=INSTANT でメタデータのみ書き換えれば瞬時に終わる
PostgreSQLDROP COLUMN はメタデータのみ更新、実データは VACUUM 後に解放される
OracleSET UNUSED で即時論理削除 → 後で DROP UNUSED COLUMNS でまとめて物理削除すると影響を分散できる
SQL ServerDROP COLUMN 自体は速いが、ROWMODCTR などのメタデータ統計再計算に時間がかかる場合がある

Oracle 特有: SET UNUSED

-- 論理削除(即時、内部的には未使用フラグを立てる)
ALTER TABLE employees SET UNUSED (middle_name);

-- 後でまとめて物理削除
ALTER TABLE employees DROP UNUSED COLUMNS;

長時間ロックを避けたいときに有効。SET UNUSED は瞬時で、物理削除をメンテ時間帯に回せます。

ロールバック性

列削除は多くの DBMS でトランザクション DDL の対象外か、サポートはあっても確実ではありません。バックアップを取ってから実行するのが鉄則です。

DBMSDDL トランザクション
PostgreSQL対応(BEGIN ~ ROLLBACK でやり直せる)
SQL Server対応(同上)
MySQL(InnoDB)非対応(即時コミット)
Oracle非対応(DDL 文の前後で暗黙コミット)

よくあるトラブル

症状原因 / 対処
外部キー違反で削除できない参照側の外部キー制約を先に DROP / または CASCADE
「列が見つかりません」大文字小文字 / 引用識別子の違い。IF EXISTS(PostgreSQL)で存在チェック
長時間ロックMySQL は INSTANT、Oracle は SET UNUSED + DROP UNUSED に分割
アプリから 500 エラー削除前に SELECT * や INSERT で当該列を使っているコードを完全に排除
容量が減らない物理的な再構築が必要なケース。OPTIMIZE TABLE(MySQL)/VACUUM FULL(PostgreSQL)/ALTER TABLE ... MOVE(Oracle)

関連

  • 表関連 — 親カテゴリ
  • 表の作成 — CREATE TABLE
  • ALTER TABLE ADD COLUMN — 列追加
  • ALTER TABLE MODIFY / RENAME COLUMN — 列変更
  • DROP TABLE — テーブルごと削除
編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 表の作成
  2. カラムの追加
  3. カラムの定義変更
  4. カラムの削除
  5. 表の削除

最近更新/作成されたページ