データベース・SQL

SQLでテーブルを作ったあとに、こんなことはありませんか?

  • 「メールアドレスの列を追加したい」
  • 「データ型を間違えたので変更したい」
  • 「もう使わない列を削除したい」
  • 「必須項目に変更したい」

そんなときに使うのが、ALTER TABLE(オルター・テーブル)です。

ALTER TABLEを使えば、すでに作ったテーブルの構造を自由に変更できます。

この記事では、ALTER TABLEの基本的な使い方から実際の例、注意点まで詳しく説明します。

スポンサーリンク

ALTER TABLEとは?

何ができるの?

ALTER TABLEは、既存のテーブルの構造を変更するSQL文です。

主な操作

  • カラム(列)の追加
  • カラムの名前変更
  • カラムのデータ型変更
  • カラムの削除
  • 制約の追加・削除
  • テーブル名の変更

基本の書き方

ALTER TABLE テーブル名 操作内容;

ALTER TABLE users ADD COLUMN email VARCHAR(100);

この例では、usersテーブルにemailという新しい列を追加しています。

カラムの追加(ADD COLUMN)

基本的な追加方法

説明 既存のテーブルに新しい列を追加します。

基本の書き方

ALTER TABLE テーブル名 ADD COLUMN カラム名 データ型;

実際の例

例1:メールアドレスの列を追加

-- usersテーブルにemailカラムを追加
ALTER TABLE users ADD COLUMN email VARCHAR(100);

例2:年齢の列を追加

-- usersテーブルにageカラムを追加
ALTER TABLE users ADD COLUMN age INT;

例3:作成日時の列を追加

-- usersテーブルにcreated_atカラムを追加
ALTER TABLE users ADD COLUMN created_at DATETIME;

制約付きで追加

例1:必須項目として追加

ALTER TABLE users ADD COLUMN phone VARCHAR(20) NOT NULL;

例2:デフォルト値付きで追加

ALTER TABLE users ADD COLUMN status VARCHAR(20) DEFAULT 'active';

例3:ユニーク制約付きで追加

ALTER TABLE users ADD COLUMN username VARCHAR(50) UNIQUE;

注意点

重要なポイント

  • 新しく追加したカラムには、既存のデータにはNULLが入る
  • NOT NULL制約を付ける場合は、DEFAULT値も一緒に指定するのが安全

よくある間違い

-- これはエラーになる可能性がある
ALTER TABLE users ADD COLUMN required_field VARCHAR(50) NOT NULL;

正しい方法

-- デフォルト値を指定する
ALTER TABLE users ADD COLUMN required_field VARCHAR(50) NOT NULL DEFAULT '';

カラムの変更

データ型の変更

説明 既存のカラムのデータ型を変更します。

MySQL の場合

ALTER TABLE テーブル名 MODIFY COLUMN カラム名 新しいデータ型;

PostgreSQL の場合

ALTER TABLE テーブル名 ALTER COLUMN カラム名 TYPE 新しいデータ型;

実際の例

例1:文字列の長さを変更(MySQL)

-- nameカラムの長さを50文字から100文字に変更
ALTER TABLE users MODIFY COLUMN name VARCHAR(100);

例2:数値型を変更(PostgreSQL)

-- ageカラムをINTからBIGINTに変更
ALTER TABLE users ALTER COLUMN age TYPE BIGINT;

例3:文字列を数値に変更(MySQL)

-- priceカラムをVARCHARからDECIMALに変更
ALTER TABLE products MODIFY COLUMN price DECIMAL(10,2);

カラム名の変更

MySQL の場合

ALTER TABLE テーブル名 CHANGE COLUMN 古い名前 新しい名前 データ型;

PostgreSQL の場合

ALTER TABLE テーブル名 RENAME COLUMN 古い名前 TO 新しい名前;

実際の例

例1:カラム名を変更(MySQL)

-- fullnameをnameに変更
ALTER TABLE users CHANGE COLUMN fullname name VARCHAR(100);

例2:カラム名を変更(PostgreSQL)

-- fullnameをnameに変更
ALTER TABLE users RENAME COLUMN fullname TO name;

カラムの削除(DROP COLUMN)

基本的な削除方法

説明 不要になったカラムをテーブルから削除します。

基本の書き方

ALTER TABLE テーブル名 DROP COLUMN カラム名;

実際の例

例1:不要なカラムを削除

-- usersテーブルからaddressカラムを削除
ALTER TABLE users DROP COLUMN address;

例2:複数のカラムを削除

-- 複数のカラムを一度に削除
ALTER TABLE users 
DROP COLUMN old_field1,
DROP COLUMN old_field2;

重要な注意点

危険性を理解する

  • 削除したカラムのデータは完全に失われます
  • 元に戻すことはできません
  • 必ず事前にバックアップを取りましょう

安全な手順

  1. バックアップを取る
  2. 削除対象のカラムを確認する
  3. テスト環境で試す
  4. 本番環境で実行する

制約の追加・削除

NOT NULL制約の追加

説明 既存のカラムに「必須項目」の制約を追加します。

MySQL の場合

ALTER TABLE users MODIFY COLUMN email VARCHAR(100) NOT NULL;

PostgreSQL の場合

ALTER TABLE users ALTER COLUMN email SET NOT NULL;

UNIQUE制約の追加

説明 重複を許さない制約を追加します。

-- emailカラムにユニーク制約を追加
ALTER TABLE users ADD CONSTRAINT unique_email UNIQUE (email);

PRIMARY KEY の追加

説明 主キーを追加します。

-- idカラムを主キーに設定
ALTER TABLE users ADD PRIMARY KEY (id);

外部キー制約の追加

説明 他のテーブルとの関連を定義します。

-- ordersテーブルのuser_idをusersテーブルのidと関連付け
ALTER TABLE orders 
ADD CONSTRAINT fk_user_id 
FOREIGN KEY (user_id) REFERENCES users(id);

制約の削除

例1:ユニーク制約の削除

ALTER TABLE users DROP CONSTRAINT unique_email;

例2:NOT NULL制約の削除(PostgreSQL)

ALTER TABLE users ALTER COLUMN email DROP NOT NULL;

テーブル名の変更

基本的な変更方法

MySQL の場合

ALTER TABLE 古いテーブル名 RENAME TO 新しいテーブル名;

PostgreSQL の場合

ALTER TABLE 古いテーブル名 RENAME TO 新しいテーブル名;

実際の例

-- usersテーブルをmembersに変更
ALTER TABLE users RENAME TO members;

実際に使える例

ユーザー管理テーブルの進化

初期のテーブル

CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(50)
);

段階1:メールアドレスを追加

ALTER TABLE users ADD COLUMN email VARCHAR(100) UNIQUE;

段階2:パスワードとステータスを追加

ALTER TABLE users 
ADD COLUMN password VARCHAR(255) NOT NULL,
ADD COLUMN status VARCHAR(20) DEFAULT 'active';

段階3:作成日時と更新日時を追加

ALTER TABLE users 
ADD COLUMN created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
ADD COLUMN updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;

段階4:名前の長さを増やす

ALTER TABLE users MODIFY COLUMN name VARCHAR(100);

商品テーブルの改善

問題のあるテーブル

CREATE TABLE products (
    id INT,
    name VARCHAR(50),
    price VARCHAR(20)  -- 文字列になっている!
);

改善手順

ステップ1:主キーを追加

ALTER TABLE products ADD PRIMARY KEY (id);

ステップ2:価格を数値型に変更

-- まず一時的なカラムを追加
ALTER TABLE products ADD COLUMN price_numeric DECIMAL(10,2);

-- データを変換してコピー
UPDATE products SET price_numeric = CAST(price AS DECIMAL(10,2));

-- 古いカラムを削除
ALTER TABLE products DROP COLUMN price;

-- 新しいカラムの名前を変更
ALTER TABLE products CHANGE COLUMN price_numeric price DECIMAL(10,2);

ステップ3:必要な制約を追加

ALTER TABLE products 
MODIFY COLUMN name VARCHAR(100) NOT NULL,
MODIFY COLUMN price DECIMAL(10,2) NOT NULL;

よくあるエラーと対処法

エラー1:カラムがすでに存在

エラーメッセージ

ERROR 1060 (42S21): Duplicate column name 'email'

原因と対処法 同じ名前のカラムを追加しようとしています。

確認方法

-- テーブル構造を確認
DESCRIBE users;
-- または
SHOW COLUMNS FROM users;

エラー2:データ型変換エラー

エラーメッセージ

ERROR: column "age" cannot be cast automatically to type integer

原因と対処法 既存のデータが新しいデータ型に変換できません。

解決手順

-- 1. 問題のあるデータを確認
SELECT age FROM users WHERE age NOT REGEXP '^[0-9]+$';

-- 2. データを修正
UPDATE users SET age = NULL WHERE age = '';
UPDATE users SET age = 0 WHERE age IS NULL;

-- 3. データ型を変更
ALTER TABLE users MODIFY COLUMN age INT;

エラー3:NOT NULL制約違反

エラーメッセージ

ERROR: column "email" contains null values

原因と対処法 NULLデータがあるカラムにNOT NULL制約を追加しようとしています。

解決手順

-- 1. NULLデータを確認
SELECT COUNT(*) FROM users WHERE email IS NULL;

-- 2. NULLデータを修正
UPDATE users SET email = 'unknown@example.com' WHERE email IS NULL;

-- 3. NOT NULL制約を追加
ALTER TABLE users MODIFY COLUMN email VARCHAR(100) NOT NULL;

エラー4:外部キー制約エラー

エラーメッセージ

ERROR: insert or update on table violates foreign key constraint

原因と対処法 参照先のテーブルに存在しないデータを参照しようとしています。

解決手順

-- 1. 問題のあるデータを確認
SELECT o.user_id 
FROM orders o 
LEFT JOIN users u ON o.user_id = u.id 
WHERE u.id IS NULL;

-- 2. データを修正してから制約を追加
DELETE FROM orders WHERE user_id NOT IN (SELECT id FROM users);

データベース別の違い

主な違い一覧

操作MySQLPostgreSQLSQLite
カラム追加ADD COLUMNADD COLUMNADD COLUMN
データ型変更MODIFY COLUMNALTER COLUMN TYPE非対応
カラム名変更CHANGE COLUMNRENAME COLUMN非対応
カラム削除DROP COLUMNDROP COLUMN非対応

SQLiteの制限

SQLiteでは多くのALTER TABLE操作が制限されています。

対処法:テーブル再作成

-- 1. 新しいテーブルを作成
CREATE TABLE users_new (
    id INT PRIMARY KEY,
    name VARCHAR(100),  -- 長さを変更
    email VARCHAR(100)  -- 新しいカラム
);

-- 2. データをコピー
INSERT INTO users_new (id, name) 
SELECT id, name FROM users;

-- 3. 古いテーブルを削除
DROP TABLE users;

-- 4. テーブル名を変更
ALTER TABLE users_new RENAME TO users;

安全な変更手順

推奨される作業手順

1. バックアップを取る

-- テーブル全体をバックアップ
CREATE TABLE users_backup AS SELECT * FROM users;

-- または
mysqldump -u username -p database_name users > users_backup.sql

2. テスト環境で試す

-- 本番と同じ構造のテストテーブルで試す
CREATE TABLE users_test AS SELECT * FROM users;
ALTER TABLE users_test ADD COLUMN email VARCHAR(100);

3. 段階的に実行

-- 一度に複数の変更をしない
ALTER TABLE users ADD COLUMN email VARCHAR(100);
-- 確認してから次の変更
ALTER TABLE users ADD COLUMN phone VARCHAR(20);

4. 確認とロールバック準備

-- 変更後の構造を確認
DESCRIBE users;

-- 問題があれば元に戻す
DROP TABLE users;
ALTER TABLE users_backup RENAME TO users;

まとめ

ALTER TABLEの基本操作

操作MySQL例PostgreSQL例
カラム追加ADD COLUMN name VARCHAR(100)ADD COLUMN name VARCHAR(100)
データ型変更MODIFY COLUMN name VARCHAR(200)ALTER COLUMN name TYPE VARCHAR(200)
カラム名変更CHANGE COLUMN old_name new_name VARCHAR(100)RENAME COLUMN old_name TO new_name
カラム削除DROP COLUMN nameDROP COLUMN name
テーブル名変更RENAME TO new_nameRENAME TO new_name

覚えておくべきポイント

基本ルール

  • ALTER TABLEは既存テーブルの構造を変更する
  • データベースによって構文が異なる
  • 変更前は必ずバックアップを取る

安全な作業

  • テスト環境で事前に確認
  • 段階的に変更を実行
  • 問題があればすぐにロールバック

よくある用途

  • 新機能に合わせたカラム追加
  • データ型の最適化
  • 不要なカラムの削除
  • 制約の追加・変更

コメント

タイトルとURLをコピーしました