MySQL の ENUM 型と SET 型
ENUM 型と SET 型は、カラムに格納できる値をあらかじめ定義したリストに制限する MySQL 固有のデータ型です。便利な反面、運用上の注意点も多いため、特性を理解した上で使う必要があります。
ENUM 型の基本
ENUM はリストの中から1つだけ値を選ぶ型です。内部的には整数(1, 2, 3…)で格納されるため、VARCHAR に比べてストレージ効率がよくなります。
CREATE TABLE tickets (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200) NOT NULL,
priority ENUM('low', 'medium', 'high', 'critical') NOT NULL DEFAULT 'medium'
);
-- 定義済みの値のみ挿入可能
INSERT INTO tickets (title, priority) VALUES ('バグ修正', 'high');
-- 定義外の値はエラー(strict モード時)
INSERT INTO tickets (title, priority) VALUES ('機能追加', 'urgent');
-- ERROR: Data truncated for column 'priority'SET 型の基本
SET は ENUM と似ていますが、リストの中から複数の値を選べる点が異なります。内部的にはビットマスクで格納されます。
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
hobbies SET('reading', 'gaming', 'cooking', 'sports') NOT NULL
);
-- 複数の値をカンマ区切りで指定
INSERT INTO users (name, hobbies) VALUES ('Alice', 'reading,cooking');
INSERT INTO users (name, hobbies) VALUES ('Bob', 'gaming');ENUM と SET の違い
リストから1つだけ選択。ストレージは1〜2バイト。最大65,535個の値を定義可能。ORDER BY でインデックス順(定義順)にソートされる。
リストから複数選択可。ストレージは1〜8バイト。最大64個の値を定義可能。FIND_IN_SET() 関数で検索する。
ENUM 型の注意点
ENUM は一見便利ですが、運用上の落とし穴があります。
新しい選択肢を追加するには ALTER TABLE でカラム定義を変更する必要があります。テーブルが大きいと、この操作に時間がかかる可能性があります。
ENUM の ORDER BY はアルファベット順ではなく、定義した順番で並びます。これを知らないと予期しないソート結果になります。
ENUM は内部的に整数ですが、数値文字列を ENUM 値にすると混乱の原因になります。ENUM(‘0’, ‘1’, ‘2’) のような定義は避けるべきです。
ENUM の代替手段
ENUM の制約が問題になる場合は、参照テーブルを作って外部キーで結ぶ方法が代替案になります。
-- 参照テーブル方式
CREATE TABLE priorities (
id TINYINT PRIMARY KEY,
name VARCHAR(20) NOT NULL UNIQUE
);
INSERT INTO priorities VALUES (1, 'low'), (2, 'medium'), (3, 'high'), (4, 'critical');
CREATE TABLE tickets (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200) NOT NULL,
priority_id TINYINT NOT NULL DEFAULT 2,
FOREIGN KEY (priority_id) REFERENCES priorities(id)
);この方式なら値の追加は INSERT だけで済み、ALTER TABLE が不要です。また、優先度に表示名や表示色などの属性を持たせたくなった場合にも、参照テーブルにカラムを追加するだけで対応できます。
どちらを選ぶか
値が今後ほぼ変わらず、選択肢が少ない場合(性別、曜日など)は ENUM で十分です。値の追加・変更が予想される場合や、選択肢に属性を持たせたい場合は参照テーブル方式が適しています。SET 型は多対多リレーションの簡易版と考えられますが、正規化の観点からは中間テーブルを使うほうが正統的な設計です。



