3.

SQL ALTER TABLE でカラム名を変更する方法(MySQL / PostgreSQL / Oracle / Laravel)

編集
この記事の要点
  • MySQL 5.x / MariaDB: ALTER TABLE t CHANGE oldname newname TYPE;(型の再指定が必須)
  • MySQL 8.0+ / PostgreSQL / SQL Server 2008+ / Oracle: ALTER TABLE t RENAME COLUMN oldname TO newname;
  • Laravel migration: $table->renameColumn("old", "new");doctrine/dbal 必須、Laravel 10.17+ で不要)
  • 運用注意: アプリ側のクエリ / ORM マッピング / インデックス名も追従させる
  • 本番運用では 新カラム追加 → データコピー → 旧カラム削除の 2 段階デプロイが安全

MySQL でのカラム名変更

MySQL はバージョンによって構文が違うのが要注意ポイント。

MySQL 5.x / MariaDB(CHANGE 構文)

-- CHANGE は型の再指定が必須
ALTER TABLE users
    CHANGE COLUMN user_name name VARCHAR(255) NOT NULL;

-- COLUMN は省略可
ALTER TABLE users
    CHANGE user_name name VARCHAR(255) NOT NULL;

-- 既存の型を変えずに名前だけ変えたい場合も、現在の型をそのまま書く必要あり
-- SHOW CREATE TABLE users; で確認

MySQL 8.0+ / MariaDB 10.5.2+(RENAME COLUMN 構文)

-- ★ 型を書かなくていい、SQL 標準と一致
ALTER TABLE users
    RENAME COLUMN user_name TO name;

-- 複数同時
ALTER TABLE users
    RENAME COLUMN first_nm TO first_name,
    RENAME COLUMN last_nm TO last_name;

PostgreSQL

-- 標準 SQL の RENAME COLUMN
ALTER TABLE users
    RENAME COLUMN user_name TO name;

-- 確認
\d users
SELECT column_name FROM information_schema.columns
WHERE table_name = 'users';

Oracle

-- Oracle 9i 以降
ALTER TABLE users
    RENAME COLUMN user_name TO name;

-- 確認
SELECT column_name FROM user_tab_columns
WHERE table_name = 'USERS';
-- ※ Oracle ではテーブル名・カラム名は大文字保存

SQL Server

-- SQL Server 2008 以降は sp_rename ストアド
EXEC sp_rename 'dbo.users.user_name', 'name', 'COLUMN';

-- SQL Server 2016+ では ALTER TABLE RENAME COLUMN も可
-- ALTER TABLE users RENAME COLUMN user_name TO name; -- (利用可能版)

DB ごとの構文比較

DB構文型の再指定
MySQL 5.x / MariaDB < 10.5ALTER TABLE t CHANGE old new TYPE★ 必須
MySQL 8.0+ / MariaDB 10.5.2+ALTER TABLE t RENAME COLUMN old TO new不要
PostgreSQL 全バージョンALTER TABLE t RENAME COLUMN old TO new不要
Oracle 9i+ALTER TABLE t RENAME COLUMN old TO new不要
SQL Server 2008+EXEC sp_rename 't.old', 'new', 'COLUMN'不要
SQLiteALTER TABLE t RENAME COLUMN old TO new(3.25.0+)不要

Laravel Migration での書き方

Laravel では renameColumn() でラップされていて DB 差分を吸収します:

// migration ファイル
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::table('users', function (Blueprint $table) {
            $table->renameColumn('user_name', 'name');
        });
    }

    public function down(): void
    {
        Schema::table('users', function (Blueprint $table) {
            $table->renameColumn('name', 'user_name');
        });
    }
};

Laravel 10.16 以前は doctrine/dbal パッケージが必要でした:

# Laravel 10.16 以下で renameColumn / change を使う場合
composer require doctrine/dbal

# Laravel 10.17 以降は不要
# https://laravel.com/docs/10.x/migrations#available-column-types

本番運用での 2 段階デプロイ

無停止デプロイ環境では、カラム名変更を一度にやると旧名でアクセスする古いコードと新名のスキーマで不整合が出ます。安全な手順:

Step 1: 新カラム追加(旧カラムも残す)
  ALTER TABLE users ADD COLUMN name VARCHAR(255);
  UPDATE users SET name = user_name;
  → アプリは旧カラム読み書き継続

Step 2: アプリを更新(読み: 新名、書き: 両方)
  $user->name = $req->name;
  $user->user_name = $req->name;   -- 互換用

Step 3: アプリを更新(読み書き: 新名のみ)
  $user->name = $req->name;

Step 4: 旧カラム削除
  ALTER TABLE users DROP COLUMN user_name;

変更時のチェックリスト

  • アプリ側コード: モデル、Repository、Raw クエリの SELECT
  • ビュー / マテビュー: 旧カラム名を参照していないか
  • ストアドプロシージャ / トリガー: 影響範囲確認
  • インデックス名: idx_user_name のような命名は別途 RENAME INDEX
  • 外部キー制約名: 自動命名されていると古いカラム名が含まれる
  • BI ツール / 集計バッチ: 別チーム管理のクエリ
  • API レスポンス: 外部クライアントへの後方互換

FAQ

Q: 大規模テーブルで ALTER TABLE を実行するとロックされる
A: MySQL 5.6+ のオンライン DDL(ALGORITHM=INPLACE)または pt-online-schema-change / gh-ost を使うとサービス停止なしで変更可能です。

Q: ロールバックしたい
A: down() で逆方向に rename。本番ではマイグレーション実行前に必ずバックアップしてください。

Q: 予約語のカラム名(例: order)に変更したい
A: バッククォート / ダブルクォートで囲めば可能ですが、後々のクエリで毎回エスケープが必要になるため非推奨です。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. テーブル作成
  2. カラムの定義変更
  3. カラム名の変更
  4. カラム追加 / 削除
  5. インデックスの作成
  6. インデックスの削除
  7. AUTO_INCREMENTの仕様について
  8. AUTO_INCREMENTの追加と確認方法
  9. 外部キーの追加/削除と制約名の確認方法

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