サービスの成長とともに、既存テーブルに新しいカラムを追加したり、型のサイズが足りなくなって変更したり、不要になった列を削除したりする作業は頻繁に発生します。
そのたびに使うのが ALTER TABLE です。ただし 数千万行のテーブルに ALTER TABLE を実行すると本番テーブルが長時間ロックされるなど、本番環境では慎重に扱う必要があります。
この記事では列の追加・削除・変更・名前変更・制約操作の基本構文から、MySQL・PostgreSQL・SQL Server の RDBMS 別の違い、本番での安全な Online DDL まで体系的に解説します。
-- 変更前の employees テーブル
CREATE TABLE employees (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
email VARCHAR(200),
salary INT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- テーブル構造の確認(MySQL)
DESCRIBE employees;
-- または
SHOW CREATE TABLE employees\G
-- テーブル構造の確認(PostgreSQL)
\d employees
-- テーブル構造の確認(SQL Server)
EXEC sp_help 'employees';
列の追加(ADD COLUMN)
ALTER TABLE テーブル名 ADD COLUMN 列名 データ型 [オプション] で列を追加します。追加した列は既存の行に対してデフォルト値(指定がなければ NULL)が設定されます。
-- 列を追加(末尾に追加)
ALTER TABLE employees ADD COLUMN phone VARCHAR(20);
-- NOT NULL + DEFAULT を指定して追加
ALTER TABLE employees ADD COLUMN status VARCHAR(20) NOT NULL DEFAULT 'active';
-- 複数列を一括追加(MySQL / Oracle)
ALTER TABLE employees
ADD COLUMN dept_id INT,
ADD COLUMN resigned_at DATE;
-- PostgreSQL / SQL Server: 複数列を一括追加
ALTER TABLE employees
ADD COLUMN dept_id INT,
ADD COLUMN resigned_at DATE; -- 同じ構文で OK
-- NOT NULL 列を既存テーブルに追加する場合
-- → 既存行に NULL が入れられないため DEFAULT 値が必須
ALTER TABLE employees
ADD COLUMN version INT NOT NULL DEFAULT 1;
-- 既存行はすべて version = 1 になる
-- 先頭に追加 ALTER TABLE employees ADD COLUMN code VARCHAR(10) FIRST; -- 特定の列の後ろに追加 ALTER TABLE employees ADD COLUMN nickname VARCHAR(100) AFTER name; -- ※ FIRST / AFTER は MySQL 独自構文 -- PostgreSQL・SQL Server では位置指定不可(末尾にしか追加できない) -- → 並び順を変えたい場合は ALTER TABLE ... テーブル再作成が必要
データが入っている既存テーブルに NOT NULL 列を追加する場合は必ず
DEFAULT 値 を指定してください。DEFAULT を指定しないと「既存行に NULL を入れられない」のでエラーになります。後から DEFAULT を削除したい場合は追加後に ALTER TABLE ... ALTER COLUMN ... DROP DEFAULT(PostgreSQL)などで対応できます。列の削除(DROP COLUMN)
ALTER TABLE テーブル名 DROP COLUMN 列名 で列を削除します。削除した列のデータは元に戻せないため、事前にバックアップを取ることを強く推奨します。
-- 列を削除
ALTER TABLE employees DROP COLUMN phone;
-- 複数列を一括削除(MySQL)
ALTER TABLE employees
DROP COLUMN dept_id,
DROP COLUMN resigned_at;
-- 存在チェック付きで削除(MySQL 8.0 / PostgreSQL 9.0 以降)
-- MySQL 8.0 以降
ALTER TABLE employees DROP COLUMN IF EXISTS phone;
-- PostgreSQL
ALTER TABLE employees DROP COLUMN IF EXISTS phone;
-- ===== 削除前の確認 =====
-- MySQL: 参照しているインデックス・制約の確認
SHOW CREATE TABLE employees\G
-- → KEY や CONSTRAINT で phone を参照していると DROP COLUMN がエラーになる
-- 外部キーが参照している列は先に外部キーを削除してから
ALTER TABLE employees DROP FOREIGN KEY fk_dept; -- 外部キー削除
ALTER TABLE employees DROP COLUMN dept_id; -- その後に列削除
DROP COLUMN を実行するとそのカラムのデータは完全に失われます。本番環境では必ず事前にバックアップを取得し、影響範囲(アプリコード・VIEW・プロシージャ)を確認してから実行してください。PostgreSQL にはすぐに物理削除しない
SET UNUSED に相当する機能はありませんが、一度 RENAME COLUMN で無効化してから後で削除する方法が使われることもあります。列のデータ型・サイズ・制約の変更(MODIFY / ALTER COLUMN)
列の型・サイズ・デフォルト値・NULL 制約を変更するには RDBMS によって構文が異なります。
| 操作 | MySQL | PostgreSQL | SQL Server |
|---|---|---|---|
| 型・サイズ変更 | MODIFY COLUMN 列名 新型 |
ALTER COLUMN 列名 TYPE 新型 |
ALTER COLUMN 列名 新型 |
| 列名変更 | RENAME COLUMN 旧名 TO 新名(8.0+)CHANGE 旧名 新名 型(旧構文) |
RENAME COLUMN 旧名 TO 新名 |
EXEC sp_rename 'テーブル.旧名', '新名', 'COLUMN' |
| NOT NULL 追加 | MODIFY COLUMN 列名 型 NOT NULL |
ALTER COLUMN 列名 SET NOT NULL |
ALTER COLUMN 列名 型 NOT NULL |
| NOT NULL 削除 | MODIFY COLUMN 列名 型 NULL |
ALTER COLUMN 列名 DROP NOT NULL |
ALTER COLUMN 列名 型 NULL |
| DEFAULT 追加 | MODIFY COLUMN 列名 型 DEFAULT 値 |
ALTER COLUMN 列名 SET DEFAULT 値 |
ADD CONSTRAINT df_name DEFAULT 値 FOR 列名 |
| DEFAULT 削除 | MODIFY COLUMN 列名 型(DEFAULT 指定なし) |
ALTER COLUMN 列名 DROP DEFAULT |
DROP CONSTRAINT df_name |
-- VARCHAR(100) → VARCHAR(200) に拡張 ALTER TABLE employees MODIFY COLUMN name VARCHAR(200) NOT NULL; -- INT → BIGINT に変更(より大きな整数が必要になった場合) ALTER TABLE employees MODIFY COLUMN salary BIGINT; -- 型変換に注意: データが入っている場合、互換性のない型変換はエラー -- NG: VARCHAR(5) に「123456」が入っている列を VARCHAR(3) に縮小 → エラー -- NG: '2024-01-15' が入っている VARCHAR 列を INT に変換 → エラー ALTER TABLE employees MODIFY COLUMN code INT; -- 文字が入っていると失敗 -- 安全な型変換のパターン -- 1. 新しい列を追加 ALTER TABLE employees ADD COLUMN salary_new DECIMAL(12,2); -- 2. データを変換してコピー UPDATE employees SET salary_new = CAST(salary AS DECIMAL(12,2)); -- 3. 古い列を削除 ALTER TABLE employees DROP COLUMN salary; -- 4. 列名を変更 ALTER TABLE employees RENAME COLUMN salary_new TO salary;
-- VARCHAR(100) → VARCHAR(200) に拡張
ALTER TABLE employees ALTER COLUMN name TYPE VARCHAR(200);
-- PostgreSQL は一部の型変換に USING 句が必要
-- TEXT → INTEGER に変換(キャスト式を指定)
ALTER TABLE employees ALTER COLUMN salary TYPE BIGINT USING salary::BIGINT;
-- VARCHAR → DATE に変換(フォーマットが合っていれば)
ALTER TABLE employees ALTER COLUMN resigned_at TYPE DATE
USING resigned_at::DATE;
-- NOT NULL 制約の追加・削除
ALTER TABLE employees ALTER COLUMN email SET NOT NULL;
ALTER TABLE employees ALTER COLUMN email DROP NOT NULL;
-- DEFAULT の追加・削除
ALTER TABLE employees ALTER COLUMN status SET DEFAULT 'active';
ALTER TABLE employees ALTER COLUMN status DROP DEFAULT;
-- VARCHAR(100) → VARCHAR(200) に拡張
ALTER TABLE employees ALTER COLUMN name VARCHAR(200) NOT NULL;
-- NOT NULL 制約の追加(型も一緒に指定が必要)
ALTER TABLE employees ALTER COLUMN email VARCHAR(200) NOT NULL;
-- NOT NULL 制約の削除(NULL 許容に変更)
ALTER TABLE employees ALTER COLUMN email VARCHAR(200) NULL;
-- DEFAULT 制約の追加(制約名付きで追加)
ALTER TABLE employees
ADD CONSTRAINT df_employees_status DEFAULT 'active' FOR status;
-- DEFAULT 制約の削除(制約名を指定)
ALTER TABLE employees DROP CONSTRAINT df_employees_status;
-- DEFAULT 制約名を確認する
SELECT name FROM sys.default_constraints
WHERE parent_object_id = OBJECT_ID('employees')
AND parent_column_id = COLUMNPROPERTY(
OBJECT_ID('employees'), 'status', 'ColumnId');
列名の変更(RENAME COLUMN)
列名を変更するには RDBMS によって構文が異なります。データ型を保持したまま名前だけを変えます。
-- ===== MySQL 8.0+ ===== ALTER TABLE employees RENAME COLUMN email TO email_address; -- MySQL 5.7 以前: CHANGE(型の再指定が必要) ALTER TABLE employees CHANGE email email_address VARCHAR(200); -- 構文: CHANGE 旧列名 新列名 データ型 [オプション] -- ===== PostgreSQL ===== ALTER TABLE employees RENAME COLUMN email TO email_address; -- ===== SQL Server ===== EXEC sp_rename 'employees.email', 'email_address', 'COLUMN'; -- ===== RENAME COLUMN の注意点 ===== -- ビュー・ストアドプロシージャ・外部キー制約が旧列名を参照している場合は -- それらも一緒に変更が必要 -- 依存関係の確認(PostgreSQL) SELECT dependent_ns.nspname, dependent_view.relname FROM pg_depend JOIN pg_rewrite ON pg_depend.objid = pg_rewrite.oid JOIN pg_class AS dependent_view ON pg_rewrite.ev_class = dependent_view.oid JOIN pg_class AS source_table ON pg_depend.refobjid = source_table.oid JOIN pg_namespace dependent_ns ON dependent_ns.oid = dependent_view.relnamespace WHERE source_table.relname = 'employees';
テーブル名の変更(RENAME TABLE)
-- ===== MySQL ===== RENAME TABLE employees TO staff; -- 複数テーブルを一括変更(アトミック操作) RENAME TABLE employees TO staff, departments TO depts; -- または ALTER TABLE employees RENAME TO staff; -- ===== PostgreSQL ===== ALTER TABLE employees RENAME TO staff; -- ===== SQL Server ===== EXEC sp_rename 'employees', 'staff'; -- または(スキーマ付き) EXEC sp_rename 'dbo.employees', 'staff'; -- ===== テーブル名変更の注意点 ===== -- ・ビュー・外部キー・ストアドプロシージャが旧テーブル名を参照していれば変更が必要 -- ・アプリケーションコードの SQL も変更が必要 -- ・MySQL の RENAME TABLE はアトミックに実行されロールバックも可能
制約の追加と削除(NOT NULL / UNIQUE / FK / CHECK)
ALTER TABLE で制約を後付けで追加・削除できます。
-- UNIQUE 制約の追加(列単位) ALTER TABLE employees ADD CONSTRAINT uq_email UNIQUE (email); -- UNIQUE インデックスとして追加(MySQL では等価) CREATE UNIQUE INDEX uq_email ON employees (email); -- UNIQUE 制約の削除 -- MySQL ALTER TABLE employees DROP INDEX uq_email; -- PostgreSQL / SQL Server ALTER TABLE employees DROP CONSTRAINT uq_email; -- 複合 UNIQUE(email + dept_id の組み合わせが一意) ALTER TABLE employees ADD CONSTRAINT uq_email_dept UNIQUE (email, dept_id);
-- CREATE TABLE departments (dept_id INT PRIMARY KEY, dept_name VARCHAR(100)); -- 外部キーの追加 ALTER TABLE employees ADD CONSTRAINT fk_dept FOREIGN KEY (dept_id) REFERENCES departments(dept_id) ON DELETE SET NULL -- 親が削除されたら NULL にする ON UPDATE CASCADE; -- 親が更新されたら連動して更新 -- 外部キーの削除 -- MySQL ALTER TABLE employees DROP FOREIGN KEY fk_dept; -- PostgreSQL / SQL Server ALTER TABLE employees DROP CONSTRAINT fk_dept; -- 外部キー名の確認(MySQL) SELECT CONSTRAINT_NAME FROM information_schema.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'employees' AND CONSTRAINT_TYPE = 'FOREIGN KEY'; -- 外部キーの一時的な無効化(MySQL) SET FOREIGN_KEY_CHECKS = 0; -- バルクインサートなど実行 SET FOREIGN_KEY_CHECKS = 1; -- 外部キーの一時的な無効化(PostgreSQL) ALTER TABLE employees DISABLE TRIGGER ALL; -- 外部キーを含むトリガー無効化 ALTER TABLE employees ENABLE TRIGGER ALL;
-- CHECK 制約の追加(salary が 0 以上)
ALTER TABLE employees
ADD CONSTRAINT chk_salary CHECK (salary >= 0);
-- CHECK 制約(status の値制限)
ALTER TABLE employees
ADD CONSTRAINT chk_status CHECK (status IN ('active', 'inactive', 'resigned'));
-- CHECK 制約の削除
ALTER TABLE employees DROP CONSTRAINT chk_salary;
-- MySQL 8.0 以前は CHECK を構文として受け付けるが無視する
-- MySQL 8.0.16 以降で CHECK 制約が有効になった
複数の変更を一括実行する
MySQL では一つの ALTER TABLE 文に複数の操作をまとめられます。一括実行することでテーブルの再構築(テーブルスキャン)が1回で済み、複数回に分けるよりパフォーマンスが向上します。
-- 複数の変更を 1 つの ALTER TABLE にまとめる
ALTER TABLE employees
ADD COLUMN dept_id INT,
ADD COLUMN resigned_at DATE,
ADD COLUMN version INT NOT NULL DEFAULT 1,
MODIFY COLUMN name VARCHAR(200) NOT NULL,
DROP COLUMN phone,
ADD CONSTRAINT uq_email UNIQUE (email),
ADD CONSTRAINT fk_dept FOREIGN KEY (dept_id) REFERENCES departments(dept_id);
-- ※ 複数回に分けると毎回テーブルが再構築される(大量データで時間がかかる)
-- 1回にまとめると再構築が1回で済む → 実行時間を大幅に短縮できる
-- PostgreSQL でも複数操作を一括実行可能
ALTER TABLE employees
ADD COLUMN dept_id INT,
ADD COLUMN resigned_at DATE,
ALTER COLUMN name TYPE VARCHAR(200),
ALTER COLUMN email SET NOT NULL,
DROP COLUMN phone;
-- PostgreSQL では ALTER TABLE 全体がトランザクション内で実行される
-- 途中でエラーが起きればすべてロールバック
本番での ALTER TABLE の注意点とオンライン DDL
数千万〜数億行のテーブルに通常の ALTER TABLE を実行すると、テーブルが長時間ロックされアプリケーションが応答しなくなることがあります。本番環境では Online DDL や専用ツールを活用してください。
| RDBMS | Online DDL の仕組み | ロック発生条件 |
|---|---|---|
| MySQL 5.6+(InnoDB) | 多くの操作が ALGORITHM=INPLACE で Online 実行可能 | 一部の操作(型変更など)は ALGORITHM=COPY でテーブルロックが発生 |
| MySQL 8.0+ | INSTANT COLUMN ADD(即座に追加・テーブル再構築なし) | DEFAULT 値なしの NOT NULL 列追加など一部はフルコピー |
| PostgreSQL | ADD COLUMN WITH DEFAULT は即座(PG11+)。インデックス追加は CONCURRENTLY で可能 | 大部分の DDL は短時間の ACCESS EXCLUSIVE ロックを取得 |
| SQL Server | Online Index Rebuild(Enterprise Edition) | Standard Edition では多くの DDL でロックが発生 |
-- ALGORITHM=INSTANT: テーブル再構築なしで即座に完了(MySQL 8.0+、列追加に対応)
ALTER TABLE employees
ADD COLUMN score INT DEFAULT 0,
ALGORITHM=INSTANT; -- テーブルロックなし・即座に完了
-- ALGORITHM=INPLACE: テーブルをコピーせず変更(多くの操作で利用可能)
ALTER TABLE employees
ADD INDEX idx_dept (dept_id),
ALGORITHM=INPLACE, LOCK=NONE; -- 読み書き並行実行可能
-- ALGORITHM=COPY: テーブル全体をコピー(古い動作・ロック発生)
ALTER TABLE employees
MODIFY COLUMN salary BIGINT,
ALGORITHM=COPY; -- 大テーブルでは時間がかかる
-- LOCK=DEFAULT / NONE / SHARED / EXCLUSIVE
-- LOCK=NONE: 読み書き両方を並行許可(不可能な操作はエラー)
-- LOCK=SHARED: 読み取りのみ並行(書き込みは待ち)
-- LOCK=EXCLUSIVE: 全操作を直列化
-- どのアルゴリズムが使われるか確認(試してみる)
-- ALGORITHM=INSTANT がサポートされなければエラーになる(実際の変更は起きない)
ALTER TABLE employees ADD COLUMN tmp INT, ALGORITHM=INSTANT;
-- 通常のインデックス作成(テーブルを短時間ロック) CREATE INDEX idx_emp_email ON employees (email); -- CONCURRENTLY: テーブルをロックせずにインデックス作成(時間はかかる) CREATE INDEX CONCURRENTLY idx_emp_email ON employees (email); -- → 読み書き並行実行中でもインデックスを作成できる -- → ただし通常より時間がかかり、失敗すると INVALID インデックスが残る -- INVALID インデックスの確認と削除 SELECT schemaname, tablename, indexname, indexdef FROM pg_indexes WHERE tablename = 'employees' AND indexname = 'idx_emp_email'; -- PostgreSQL 11 以降: DEFAULT 値付き列の追加が即座(テーブルスキャンなし) ALTER TABLE employees ADD COLUMN score INT DEFAULT 0; -- PG10 以前: 全行を更新するためテーブルスキャンが発生
-- pt-online-schema-change(Percona Toolkit) -- テーブルをコピーしながら変更・元テーブルをアトミックにリネーム -- → 数億行のテーブルでも無停止で ALTER TABLE 相当の操作が可能 -- 実行コマンド例(コマンドライン) -- pt-online-schema-change \ -- --alter "ADD COLUMN score INT DEFAULT 0" \ -- --execute \ -- D=mydb,t=employees -- gh-ost(GitHub 製) -- バイナリログを利用したオンラインスキーマ変更ツール -- より安全で進捗管理・一時停止・再開が可能 -- gh-ost 実行コマンド例 -- gh-ost \ -- --database="mydb" \ -- --table="employees" \ -- --alter="ADD COLUMN score INT DEFAULT 0" \ -- --execute -- どちらも大きなテーブルで ALTER TABLE を安全に実行するための定番ツール
- テーブルサイズの確認: 数百万行を超えるテーブルは Online DDL ツールの利用を検討する
- ALGORITHM=INSTANT の確認: MySQL 8.0 なら列追加は INSTANT で即座に完了するか試す
- 実行時間の見積もり: ステージング環境で同等サイズのテーブルで事前にテスト
- ロック影響範囲: 実行中に待ちが発生するクエリがないか ロック状態を監視する
- バックアップ: DROP COLUMN・型変更の前は必ずバックアップを取得
- 依存関係の確認: VIEW・ストアドプロシージャ・アプリコードが影響を受けないか確認
ALTER TABLE でよくあるエラーと対処法
| エラー | RDBMS | 原因 | 対処法 |
|---|---|---|---|
Column count doesn't match... |
MySQL | INSERT INTO … SELECT のカラム数が合わない | SELECT 列数を INSERT 先と合わせる |
Cannot add or update a child row: a foreign key constraint fails |
MySQL | 外部キー制約のある列に制約に違反する値を追加しようとした | 先に親テーブルのデータを整合させるか SET FOREIGN_KEY_CHECKS=0 で一時無効化 |
Invalid use of NULL value |
MySQL | NULL が入っている列に NOT NULL を追加しようとした | 先に UPDATE ... WHERE col IS NULL で NULL を解消してから制約を追加 |
column "x" of relation "y" already exists |
PostgreSQL | 既存の列名と同じ名前で ADD COLUMN しようとした | 別の名前を使うか ADD COLUMN IF NOT EXISTS(PG9.6+)を使う |
Lock wait timeout exceeded |
MySQL | 長時間実行されているクエリがテーブルをロック中 | SHOW PROCESSLIST で原因クエリを特定して KILL |
data type incompatible |
PostgreSQL | USING 句なしに互換性のない型変換を試みた | USING 列名::新型 でキャスト式を明示する |
-- ① 現在の NULL 状況を確認 SELECT COUNT(*) FROM employees WHERE email IS NULL; -- ② NULL 行を更新してから制約を追加 UPDATE employees SET email = 'unknown@example.com' WHERE email IS NULL; -- ③ NOT NULL 制約を追加 -- MySQL ALTER TABLE employees MODIFY COLUMN email VARCHAR(200) NOT NULL; -- PostgreSQL ALTER TABLE employees ALTER COLUMN email SET NOT NULL; -- ④ DEFAULT も同時に設定しておくと今後の INSERT で NULL が入らなくなる ALTER TABLE employees MODIFY COLUMN email VARCHAR(200) NOT NULL DEFAULT ''; -- または: ALTER TABLE employees MODIFY COLUMN status VARCHAR(20) NOT NULL DEFAULT 'active';
よくある質問(FAQ)
ADD COLUMN は ALGORITHM=INSTANT で即座に完了しロックが発生しません。しかし MODIFY COLUMN(型変更)は内部でテーブル全体をコピーするため、数百万行のテーブルでは数分〜数十分かかりその間ロックが発生します。本番環境では事前にステージングで実行時間を確認し、必要に応じて pt-osc や gh-ost を使ってください。ADD COLUMN ... AFTER 列名 / FIRST で追加位置を指定できます。ただし既存の列の順序を並び替える操作はどの RDBMS も標準的な方法はなく、テーブルを新規作成して INSERT INTO ... SELECT でデータを移行する方法が一般的です。実務では「列の並び順」を気にするより SELECT 時に必要な列を明示する設計のほうが重要です。DEFAULT 値 を指定している場合はその値が既存行に設定されます。DEFAULT を指定しなかった場合は NULL が設定されます(NOT NULL 制約がある場合はエラー)。MySQL 8.0 の INSTANT 追加では実際には行を更新せず、デフォルト値はメタデータに記録されて SELECT 時に返します(物理行は変更されません)。SELECT ... WHERE dept_id NOT IN (SELECT dept_id FROM departments) のような SQL で孤立データを確認・修正してから外部キーを追加してください。一時的に外部キーチェックを無効化して追加することもできますが、データ品質の問題を後回しにするためお勧めしません。まとめ
ALTER TABLE の操作パターンを一覧表でまとめます。
| 操作 | MySQL | PostgreSQL | SQL Server |
|---|---|---|---|
| 列の追加 | ADD COLUMN 名 型 [FIRST|AFTER 列] |
ADD COLUMN 名 型 |
ADD 名 型 |
| 列の削除 | DROP COLUMN 名 |
DROP COLUMN [IF EXISTS] 名 |
DROP COLUMN 名 |
| 型・サイズ変更 | MODIFY COLUMN 名 新型 |
ALTER COLUMN 名 TYPE 新型 [USING] |
ALTER COLUMN 名 新型 |
| 列名変更 | RENAME COLUMN 旧 TO 新(8.0+) |
RENAME COLUMN 旧 TO 新 |
EXEC sp_rename 'tbl.旧', '新', 'COLUMN' |
| テーブル名変更 | RENAME TO 新名 |
RENAME TO 新名 |
EXEC sp_rename '旧', '新' |
| NOT NULL 追加 | MODIFY COLUMN 名 型 NOT NULL |
ALTER COLUMN 名 SET NOT NULL |
ALTER COLUMN 名 型 NOT NULL |
| DEFAULT 追加 | MODIFY COLUMN 名 型 DEFAULT 値 |
ALTER COLUMN 名 SET DEFAULT 値 |
ADD CONSTRAINT df名 DEFAULT 値 FOR 名 |
| UNIQUE 追加 | ADD CONSTRAINT 制約名 UNIQUE (列名)(共通) |
||
| 外部キー追加 | ADD CONSTRAINT 制約名 FOREIGN KEY (列) REFERENCES 親(列)(共通) |
||
本番環境では ALTER TABLE を実行する前に必ずテーブルサイズとロックの影響を確認し、大量テーブルには Online DDL(ALGORITHM=INSTANT/INPLACE)やpt-online-schema-change・gh-ost の活用を検討してください。
テーブルの削除はDROP TABLE の完全ガイドを、プライマリーキーの操作はプライマリーキーの追加と削除を参照してください。

