文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 參考手冊  /  ...  /  ENUM 類型

13.3.6 ENUM 類型

ENUM 是一個字串物件,其值是從表格建立時在欄位規格中明確列舉的允許值清單中選擇的。

請參閱第 13.3.1 節「字串資料類型語法」,以了解 ENUM 類型語法和長度限制。

ENUM 類型具有以下優點:

  • 在欄位具有一組有限的可能值的情況下,可進行精簡的資料儲存。您指定為輸入值的字串會自動編碼為數字。有關 ENUM 類型的儲存需求,請參閱第 13.7 節「資料類型儲存需求」

  • 可讀取的查詢和輸出。數字會在查詢結果中轉譯回對應的字串。

以及以下需要考慮的潛在問題:

  • 如果您建立看起來像數字的列舉值,則很容易將文字值與其內部索引號混淆,如列舉限制中所述。

  • ORDER BY 子句中使用 ENUM 欄位需要格外小心,如列舉排序中所述。

建立和使用 ENUM 欄位

列舉值必須是帶引號的字串文字。例如,您可以像這樣建立具有 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' 的列舉成員,但數值索引值為 123

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 值會以字串形式傳回。如需有關使用結果集 Metadata 將它們與其他字串區分的相關資訊,請參閱C API 基本資料結構

空值或 NULL 列舉值

在某些情況下,列舉值也可以是空字串 ('') 或 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')
);

我們強烈建議您不要使用數字作為列舉值,因為這樣並不會比使用適當的 TINYINTSMALLINT 類型節省儲存空間,而且如果您錯誤地引用 ENUM 值,很容易混淆字串和基礎數字值(可能不一樣)。如果您確實使用數字作為列舉值,請務必將其括在引號中。如果省略引號,則該數字會被視為索引。請參閱列舉常值的處理,以了解即使是帶引號的數字也可能被錯誤地用作數值索引值。

定義中的重複值會導致警告,如果啟用了嚴格 SQL 模式,則會導致錯誤。