文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (美式 Letter) - 39.9Mb
PDF (A4) - 40.0Mb
手冊頁 (TGZ) - 258.5Kb
手冊頁 (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


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

13.3.5 ENUM 類型

ENUM 是一種字串物件,其值是從表格建立時在資料行規格中明確列舉的允許值清單中選取的。

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

ENUM 類型具有以下優點

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

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

以及需要考量的這些潛在問題

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

  • 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;

將 100 萬列資料插入到此表格中,且值為 'medium',則需要 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 值會以字串的形式傳回。如需使用結果集中繼資料將它們與其他字串區分開來的資訊,請參閱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 模式,則會導致錯誤。