9.

DB2のカラムの追加/削除/変更

編集
この記事の要点
  • DB のカラム操作は ALTER TABLE
  • 追加: ALTER TABLE t ADD COLUMN col TYPE [制約]
  • 削除: ALTER TABLE t DROP COLUMN col
  • 型変更: ALTER TABLE t MODIFY col NEW_TYPE (MySQL) / ALTER COLUMN col TYPE NEW_TYPE (PostgreSQL)
  • 名前変更: ALTER TABLE t CHANGE old_col new_col TYPE (MySQL) / RENAME COLUMN (PG/SQL Server)

 

カラム追加

-- 基本
ALTER TABLE users ADD COLUMN phone VARCHAR(20);

-- 制約付き
ALTER TABLE users ADD COLUMN phone VARCHAR(20) NOT NULL DEFAULT '';

-- 既存カラムの後ろに挿入 (MySQL)
ALTER TABLE users ADD COLUMN phone VARCHAR(20) AFTER email;

-- 先頭に
ALTER TABLE users ADD COLUMN phone VARCHAR(20) FIRST;

-- 複数列を一度に
ALTER TABLE users
    ADD COLUMN phone VARCHAR(20),
    ADD COLUMN birth_date DATE,
    ADD COLUMN bio TEXT;

-- インデックスや外部キーも同時
ALTER TABLE orders
    ADD COLUMN customer_id BIGINT,
    ADD INDEX idx_orders_customer (customer_id),
    ADD FOREIGN KEY (customer_id) REFERENCES customers(id);

カラム削除

-- 単一カラム
ALTER TABLE users DROP COLUMN obsolete_field;

-- 複数列
ALTER TABLE users
    DROP COLUMN field1,
    DROP COLUMN field2;

-- 制約も一緒に削除 (PostgreSQL CASCADE)
ALTER TABLE users DROP COLUMN field CASCADE;

-- 警告:
-- - 削除前にバックアップ
-- - 関連する INDEX も自動削除
-- - 外部キー参照されていると失敗

型変更

MySQL

-- MODIFY (型のみ変更)
ALTER TABLE users MODIFY phone VARCHAR(30);

-- 既存制約をそのまま
ALTER TABLE users MODIFY phone VARCHAR(30) NOT NULL DEFAULT '';

-- 型変更 + 名前変更 (CHANGE)
ALTER TABLE users CHANGE phone phone_number VARCHAR(30);

-- 注意: 互換性のない型変更はデータ損失リスク
-- VARCHAR(100) → VARCHAR(10) で 11 文字以上は切り捨て (or エラー)

PostgreSQL

-- ALTER COLUMN
ALTER TABLE users ALTER COLUMN phone TYPE VARCHAR(30);

-- 暗黙変換できない場合 USING
ALTER TABLE users ALTER COLUMN age TYPE INTEGER USING age::integer;
ALTER TABLE users ALTER COLUMN created TYPE TIMESTAMP USING created::timestamp;

-- 制約の追加/削除
ALTER TABLE users ALTER COLUMN phone SET NOT NULL;
ALTER TABLE users ALTER COLUMN phone DROP NOT NULL;
ALTER TABLE users ALTER COLUMN phone SET DEFAULT 'unknown';
ALTER TABLE users ALTER COLUMN phone DROP DEFAULT;

Oracle

-- 型変更
ALTER TABLE users MODIFY phone VARCHAR2(30);

-- NULL → NOT NULL
ALTER TABLE users MODIFY phone NOT NULL;

-- デフォルト値
ALTER TABLE users MODIFY phone DEFAULT '';

SQL Server

-- 型変更
ALTER TABLE users ALTER COLUMN phone VARCHAR(30);

-- NULL 制約
ALTER TABLE users ALTER COLUMN phone VARCHAR(30) NOT NULL;

カラム名変更

-- MySQL (CHANGE で型必須)
ALTER TABLE users CHANGE phone phone_number VARCHAR(20);

-- MySQL 8+ (RENAME COLUMN)
ALTER TABLE users RENAME COLUMN phone TO phone_number;

-- PostgreSQL
ALTER TABLE users RENAME COLUMN phone TO phone_number;

-- Oracle
ALTER TABLE users RENAME COLUMN phone TO phone_number;

-- SQL Server (sp_rename)
EXEC sp_rename 'users.phone', 'phone_number', 'COLUMN';

テーブル名変更

-- MySQL / PostgreSQL / Oracle
ALTER TABLE users RENAME TO members;

-- SQL Server
EXEC sp_rename 'users', 'members';

-- MySQL の RENAME TABLE (複数テーブルまとめて)
RENAME TABLE users TO members, orders TO order_history;

制約の追加・削除

-- UNIQUE 制約
ALTER TABLE users ADD UNIQUE (email);
ALTER TABLE users ADD CONSTRAINT uk_users_email UNIQUE (email);

-- 削除
ALTER TABLE users DROP INDEX uk_users_email;  -- MySQL
ALTER TABLE users DROP CONSTRAINT uk_users_email;  -- PG/SQL Server

-- CHECK 制約
ALTER TABLE products ADD CONSTRAINT chk_price_positive CHECK (price > 0);
ALTER TABLE products DROP CONSTRAINT chk_price_positive;

-- 外部キー
ALTER TABLE orders ADD CONSTRAINT fk_orders_user
    FOREIGN KEY (user_id) REFERENCES users(id);
ALTER TABLE orders DROP FOREIGN KEY fk_orders_user;  -- MySQL
ALTER TABLE orders DROP CONSTRAINT fk_orders_user;  -- PG/SQL Server

-- インデックス
CREATE INDEX idx_users_status ON users (status);
DROP INDEX idx_users_status;        -- PostgreSQL/Oracle/SQL Server
ALTER TABLE users DROP INDEX idx_users_status;  -- MySQL

大規模テーブルでの注意

本番の大規模テーブル ALTER は時間がかかり、ロックが発生します:

# テーブルロック中は SELECT / INSERT すらブロック (DB により異なる)

# 対処 1: PT-OSC (Percona Toolkit) でオンライン ALTER
$ pt-online-schema-change --alter "ADD COLUMN phone VARCHAR(20)" \
    D=mydb,t=users --execute
# → 一時テーブル + トリガで段階的に変更、ダウンタイムなし

# 対処 2: gh-ost (GitHub 製)
$ gh-ost --database=mydb --table=users \
    --alter="ADD COLUMN phone VARCHAR(20)" \
    --execute

# 対処 3: アプリ側でテーブル分割 (シャーディング)

# 対処 4: PostgreSQL は基本的に CONCURRENTLY で非ブロック
CREATE INDEX CONCURRENTLY idx_users_phone ON users (phone);

# 対処 5: SQL Server は ONLINE オプション (Enterprise)
ALTER INDEX ALL ON users REBUILD WITH (ONLINE = ON);

マイグレーションツール (推奨)

本番では直接 ALTER せず、マイグレーションツール経由:

言語/FWツール
Java / SpringFlyway / Liquibase
Laravelphp artisan make:migration
Railsrails g migration
Djangopython manage.py makemigrations
Node.jsKnex / Sequelize / TypeORM

Flyway の例

# src/main/resources/db/migration/V20260515__add_phone_to_users.sql
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
CREATE INDEX idx_users_phone ON users(phone);

# Spring Boot 起動時に自動実行

Laravel

$ php artisan make:migration add_phone_to_users_table --table=users

# database/migrations/xxxx_add_phone_to_users_table.php
public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('phone', 20)->nullable()->after('email');
    });
}

public function down()
{
    Schema::table('users', function (Blueprint $table) {
        $table->dropColumn('phone');
    });
}

# 実行
$ php artisan migrate
$ php artisan migrate:rollback

変更履歴・記録のベストプラクティス

  • マイグレーションファイル: バージョン管理 (Git)
  • 命名規則: V20260515_001__add_phone.sql 形式
  • ロールバック手順: 必ず down() / 逆 SQL を用意
  • 本番前にステージング: 大規模テーブルは事前検証
  • レビュー: PR で SQL を確認
  • バックアップ: ALTER 前に必ず

関連記事

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. DB接続コマンド
  2. データベース一覧の確認
  3. テーブル一覧の確認
  4. テーブル定義の確認
  5. DBの設定確認
  6. テーブルスペースの容量の確認および拡張
  7. データ型
  8. 複数カラムのUPDATE
  9. カラムの追加/削除/変更
  10. 自動番号付け (autoincrement) する方法
  11. インデックスの作成
  12. シーケンスおよびインクリメント(ID列)の違いと確認方法
  13. create table文の生成
  14. 特定スキーマの全テーブルの全カラム情報を取得する方法
  15. 【DB2】エラー一覧
  16. 【DB2】テーブル定義からCREATE TABLE文を生成する方法