ENUM
は、テーブル作成時にカラム仕様に明示的に列挙された、許可されている値のリストから選択された値を持つ文字列オブジェクトです。
ENUM
型の構文および長さの制限については、セクション11.3.1「文字列データ型の構文」 を参照してください。
ENUM
タイプには、次の利点があります:
指定可能な値のセットがカラムで制限されている状況でのコンパクトなデータストレージ。 入力値として指定した文字列は自動的に数値としてエンコードされます。
ENUM
タイプの記憶域要件については、セクション11.7「データ型のストレージ要件」 を参照してください。読みやすいクエリーと出力。 数値は、クエリー結果で対応する文字列に戻されます。
また、次のような考慮が必要な問題が生じる可能性があります。
列挙値は引用符で囲んだ文字列リテラルにする必要があります。 たとえば、次のように ENUM
カラムを持つテーブルを作成できます。
CREATE TABLE shirts (
name VARCHAR(40),
size ENUM('x-small', 'small', 'medium', 'large', 'x-large')
);
INSERT INTO shirts (name, size) VALUES ('dress shirt','large'), ('t-shirt','medium'),
('polo shirt','small');
SELECT name, size FROM shirts WHERE size = 'medium';
+---------+--------+
| name | size |
+---------+--------+
| t-shirt | medium |
+---------+--------+
UPDATE shirts SET size = 'small' WHERE size = 'large';
COMMIT;
'medium'
の値を持つ 100 万個の行をこのテーブルに挿入するには、100 万バイトのストレージが必要ですが、実際の文字列 'medium'
を VARCHAR
カラムに格納した場合は、600 万バイト必要になります。
それぞれの列挙値にはインデックスが設定されています。
カラム仕様にリストされている要素には、1 から始まるインデックス番号が割り当てられています。
-
空の文字列エラー値のインデックス値は 0 です。 つまり、次の
SELECT
ステートメントを使用して、無効なENUM
値が割り当てられた行を検索できます。mysql> SELECT * FROM tbl_name WHERE enum_col=0;
NULL
値のインデックスはNULL
です。ここでの「インデックス」という語は、列挙値のリスト内での位置を示します。 これは、テーブルインデックスとはまったく関係ありません。
たとえば、ENUM('Mercury', 'Venus', 'Earth')
と指定されたカラムには、次に示すどの値でも含めることができます。 それぞれの値のインデックスも示しています。
値 | インデックス |
---|---|
NULL |
NULL |
'' |
0 |
'Mercury' |
1 |
'Venus' |
2 |
'Earth' |
3 |
ENUM
カラムには、最大 65,535 個の個別の要素を含めることができます。
ENUM
値を数値コンテキストで取得した場合、カラム値のインデックスが返されます。 たとえば、次のように ENUM
カラムから数値を取得できます。
mysql> SELECT enum_col+0 FROM tbl_name;
数値引数を取る SUM()
や AVG()
などの関数は、必要に応じて引数を数値にキャストします。 ENUM
値の計算にはインデックス番号が使用されます。
テーブルが作成されるときに、テーブル定義内の ENUM
メンバー値から末尾のスペースが自動的に削除されます。
ENUM
カラムに格納された値は、取得されたときに、カラム定義で使用された大文字/小文字で表示されます。 ENUM
カラムには文字セットと照合順序を割り当てられています。 バイナリ照合順序、または大文字と小文字を区別する照合順序の場合、カラムに値を割り当てるときに、大文字/小文字が考慮されます。
ENUM
カラムに数字を格納すると、その数字は指定可能な値のインデックスとして扱われ、格納された値がそのインデックスを持つ列挙メンバーとなります。 (ただし、これはすべての入力を文字列として扱う LOAD DATA
では機能 しません。) 数値が引用符で囲まれている場合、列挙値のリストに一致する文字列がなければ、そのままインデックスとして解釈されます。 これらの理由により、ENUM
カラムを数字のように見える列挙値で定義することは、混乱を招きやすくなるのでお勧めできません。 たとえば、次のカラムには '0'
、'1'
、および '2'
の文字列値を持つ列挙メンバーが指定されていますが、数値インデックス値は 1
、2
、および 3
です。
numbers ENUM('0','1','2')
2
を格納すると、それはインデックス値と解釈され、'1'
(インデックス 2 の値) になります。 '2'
を格納すると、それは列挙値と一致するので、'2'
として格納されます。 '3'
を格納すると、どの列挙値とも一致しないのでインデックスとして扱われ、'2'
(インデックス 3 の値) になります。
mysql> INSERT INTO t (numbers) VALUES(2),('2'),('3');
mysql> SELECT * FROM t;
+---------+
| numbers |
+---------+
| 1 |
| 2 |
| 2 |
+---------+
ENUM
カラムのすべての指定可能な値を特定するには、SHOW COLUMNS FROM
を使用して、出力の tbl_name
LIKE 'enum_col
'Type
カラム内の ENUM
定義を構文解析します。
C API では、ENUM
値は文字列として返されます。 結果セットのメタデータを使用してこれらをほかの文字列から区別する方法については、C API Basic Data Structuresを参照してください。
以下のような特定の状況下では、列挙値は、空の文字列 (''
) や NULL
になることもあります。
-
ENUM
に無効な値 (つまり、許可された値のリストに存在しない文字列) を挿入すると、特殊なエラー値として空の文字列が代わりに挿入されます。 この文字列は、この文字列に 0 の数値が含まれていることで、「通常」の空の文字列と区別できます。 列挙値の数値インデックスの詳細は、列挙リテラルのインデックス値を参照してください。厳密な SQL モードが有効な場合は、無効な
ENUM
値を挿入しようとするとエラーが発生します。 ENUM
カラムがNULL
を許可するように宣言されている場合、NULL
値は、そのカラムに対して有効な値であり、デフォルト値はNULL
になります。ENUM
カラムがNOT NULL
として宣言されている場合、デフォルト値は許可されている値のリストの最初の要素になります。
ENUM
値は、インデックス番号に基づいてソートされますが、この数値は、カラム仕様で列挙メンバーがリストされていた順序に従います。 たとえば、ENUM('b', 'a')
の場合、'b'
は 'a'
の前にソートされます。 空の文字列は空ではない文字列の前にソートされ、NULL
値はその他のすべての列挙値の前にソートされます。
ENUM
カラムで ORDER BY
句の使用時に予想外の結果になることを回避するには、次のいずれかの手法を使用します。
アルファベット順で
ENUM
リストを指定します。ORDER BY CAST(
またはcol
AS CHAR)ORDER BY CONCAT(
をコード化することにより、カラムがインデックス番号ではなく、辞書順でソートされることを確認します。col
)
列挙値は、文字列値に評価されるものであっても、式にはできません。
たとえば、次の CREATE TABLE
ステートメントは、CONCAT
関数を列挙値の構築に使用できないので、機能しません。
CREATE TABLE sizes (
size ENUM('small', CONCAT('med','ium'), 'large')
);
ユーザー変数を列挙値として使用することもできません。 次のステートメントのペアは機能しません。
SET @mysize = 'medium';
CREATE TABLE sizes (
size ENUM('small', @mysize, 'large')
);
数字を列挙値として使用しないことを強くお勧めします。これは、適切な TINYINT
または SMALLINT
型よりもストレージを節約するわけでもなく、ENUM
値を間違って引用符で囲んだ場合には、文字列とベースになる数値とを混同しやすくなる (同じでない場合もあります) からです。 数字を列挙値として使用する場合は、必ず引用符で囲んでください。 引用符を省略した場合は、その数字はインデックスと見なされます。 列挙リテラルの処理を参照して、引用符で囲まれた数字でも間違って数字のインデックス値として使用されるか場合について確認してください。
定義の中に重複した値が含まれていると、警告 (厳密な SQL モードが有効になっている場合はエラー) が発生します。