😸

MySQLのENUM型 詳解

2023/09/12に公開

ENUM型とは

ENUMは、テーブル作成時に列挙された事前定義リストから選択された値を持つデータ型です。この事前定義リスト外の値を入力しようとするとエラーが発生します。
ENUMは文字列のように見えますが、内部的には整数として格納されています。
ENUMは文字列の可読性と整数のコンパクトなデータ型を兼ね備えています。

ENUM型の内部表現

ENUMがどのように機能するかを見るために、価格列をENUMとして宣言した商品テーブルを作成しましょう。価格列は"cheap", "reasonable", "expensive"の3つの値をとるENUMとして定義します。

CREATE TABLE products (
  id INT AUTO_INCREMENT PRIMARY KEY,
  price ENUM('cheap', 'reasonable', 'expensive')
);


INSERT INTO products (price) VALUES ('cheap'), ('reasonable'), ('expensive');

挿入された価格列を整数型として表示してみましょう。

SELECT price, price+0 FROM products;

このクエリは次の結果を返します:

+------------+--------+
| size       | size+0 |
+------------+--------+
| cheap      |      1 |
| reasonable |      2 |
| expensive  |      3 |
+------------+--------+

事前定義リストで列挙された順に1,2,3と整数値が割り当てられているのが確認できます。

ENUMの利点

MySQLでENUMを使用することには、次のようないくつかの利点があります

データの自動検証

前述のように、ENUMはデータの検証を提供し、列に有効なデータのみがデータベースに入力されることを保証します。
無効な値を入力しようとするとエラーが発生し、データがデータベースに挿入されるのを防ぎます。これはセキュリティの向上にも寄与します。

可読性の向上

文字列を整数にエンコードする代わりにENUMを使用することで、データベースに可読性の高い値を保存できるため、データを一目で理解することができます。

コンパクトなデータ型

ENUMはコンパクトなデータ型であり、文字列などの他のデータ型よりもストレージスペースを小さく抑えることができます。

ENUMのデメリット

ENUMを使用する際にはいくつかのデメリットも考慮する必要があります。これには次のようなものがあります

スキーマの変更

業務要件が変更され、許容される値に別のオプションを追加する必要がある場合、テーブルのスキーマを変更する必要があります。

ソート

ENUMを使用してデータをソートする場合、MySQLは実際の文字列ではなく、内部表現の整数値(事前定義リストに定義された順)でソートします。
実際の文字列でソートするには以下のいずれかようにする必要があります。

  • 事前定義リストにおいてアルファベット順でENUMを定義する。
  • ORDER BY CAST(col AS CHAR)またはORDER BY CONCAT(col)として、カラムが辞書順でソートされるようにする。

整数値に対するENUMの使用

整数をENUMとして使用すると実際の値と内部表現の値が混同されるためできる限り避けるべきです。

例えば以下のようにテーブルを定義します。

CREATE TABLE test (
  numbers  ENUM( '5', '4', '3', '2', '1' )
);
 
INSERT INTO test (numbers) VALUES ('2'), ('4'), ('1');

次に以下のようなSELECT文を実行します。

SELECT numbers from test where numbers = "2";
/* 文字列で比較すると実際の値で比較され、"2"が返る */
+---------+
| numbers |
| 2       |
+---------+

SELECT numbers from test where numbers = 2; 
/* 整数値で比較すると内部表現の値で比較され、2番目に定義された"4"が返る */
+---------+
| numbers |
| 4       |
+---------+

このように整数をENUMとして格納すると非常にややこしくなります。
単にデータサイズを削減したいだけならTINYINTを使用しましょう。

まとめ

MySQLにおけるENUMは、データサイズを削減し、安全性・可読性を可読性を向上させる強力な機能です。
ただし、ENUMの使用時は事前定義リスト変更時にテーブルのスキーマを変更する必要があります。またソート時は文字列ではなく内部表現の整数値でソートされるという直感に反する挙動があります。
これらの挙動を理解して正しくENUMを使うことが重要です。

参考資料

https://dev.mysql.com/doc/refman/8.0/ja/storage-requirements.html
https://planetscale.com/learn/courses/mysql-for-developers/schema/enums

関連リンク

MySQLの整数値型 詳解
MySQLの小数値型 詳解
MySQLの文字列型 CHAR,VARCHAR 詳解
MySQLのバイナリデータ型 BINARY、VARBINARY 詳解
MySQLのTEXT、BLOB 詳解
MySQLの時間データ型 詳解
MySQLのJSON型 詳解
MySQL - innodbにおける各データ型のサイズまとめ

Discussion