MySQL
ENUM
Sök…
Varför ENUM?
ENUM ger ett sätt att tillhandahålla ett attribut för en rad. Attribut med ett litet antal icke-numeriska alternativ fungerar bäst. Exempel:
reply ENUM('yes', 'no')
gender ENUM('male', 'female', 'other', 'decline-to-state')
Värdena är strängar:
INSERT ... VALUES ('yes', 'female')
SELECT ... --> yes female
TINYINT som ett alternativ
Låt oss säga att vi har det
type ENUM('fish','mammal','bird')
Ett alternativ är
type TINYINT UNSIGNED
plus
CREATE TABLE AnimalTypes (
type TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(20) NOT NULL COMMENT "('fish','mammal','bird')",
PRIMARY KEY(type),
INDEX(name)
) ENGINE=InnoDB
vilket är mycket som ett många-till-många-bord.
Jämförelse, och om det är bättre eller sämre än ENUM:
- (värre) INSERT: måste leta upp
type
- (sämre) VÄLJ: måste gå med i JOIN för att få strängen (ENUM ger dig strängen utan ansträngning)
- (bättre) Lägga till nya typer: Infoga bara i den här tabellen. Med ENUM måste du göra en ALTER-TABELL.
- (samma) Endera tekniken (för upp till 255 värden) tar bara 1 byte.
- (blandat) Det finns också en fråga om dataintegritet:
TINYINT
medger ogiltiga värden;ENUM
ställer in dem till ett speciellt tomsträngsvärde (såvida inte strikt SQL-läge är aktiverat, i vilket fall de avvisas). Bättre dataintegritet kan uppnås medTINYINT
genom att göra det till en utländsk nyckel till en uppslagstabell: som, med lämpliga frågor / sammanfogningar, men det finns fortfarande de lilla kostnaderna för att nå den andra tabellen. (FOREIGN KEYs
är inte gratis.)
VARCHAR som ett alternativ
Låt oss säga att vi har det
type ENUM('fish','mammal','bird')
Ett alternativ är
type VARCHAR(20) COMENT "fish, bird, etc"
Detta är ganska öppet genom att nya typer läggs till.
Jämförelse, och om det är bättre eller sämre än ENUM:
- (samma) INSERT: ange bara strängen
- (sämre?) På INSERT kommer en skrivfel att bli obemärkt
- (samma) VÄLJ: den aktuella strängen returneras
- (värre) Mycket mer utrymme förbrukas
Lägga till ett nytt alternativ
ALTER TABLE tbl MODIFY COLUMN type ENUM('fish','mammal','bird','insect');
anteckningar
- Som med alla fall av MODIFY COLUMN, måste du inkludera
NOT NULL
och alla andra kval som tidigare fanns, annars kommer de att gå förlorade. - Om du lägger till i slutet av listan och listan är under 256 objekt görs
ALTER
genom att bara ändra schemat. Det är att det inte kommer att finnas en lång tabellkopia. (Gamla versioner av MySQL hade inte denna optimering.)
NULL vs INTE NULL
Exempel på vad som händer när NULL och ”dåligt värde” lagras i nollbara och inte nullable kolumner. Visar också användning av casting till numerisk via +0
.
CREATE TABLE enum (
e ENUM('yes', 'no') NOT NULL,
enull ENUM('x', 'y', 'z') NULL
);
INSERT INTO enum (e, enull)
VALUES
('yes', 'x'),
('no', 'y'),
(NULL, NULL),
('bad-value', 'bad-value');
Query OK, 4 rows affected, 3 warnings (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 3
mysql>SHOW WARNINGS;
+---------+------+--------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------+
| Warning | 1048 | Column 'e' cannot be null |
| Warning | 1265 | Data truncated for column 'e' at row 4 |
| Warning | 1265 | Data truncated for column 'enull' at row 4 |
+---------+------+--------------------------------------------+
3 rows in set (0.00 sec)
Vad finns i tabellen efter dessa insatser. Detta använder "+0" för att skicka till numeriskt för att se vad som är lagrat.
mysql>SELECT e, e+0 FROM enum;
+-----+-----+
| e | e+0 |
+-----+-----+
| yes | 1 |
| no | 2 |
| | 0 | -- NULL
| | 0 | -- 'bad-value'
+-----+-----+
4 rows in set (0.00 sec)
mysql>SELECT enull, enull+0 FROM enum;
+-------+---------+
| enull | enull+0 |
+-------+---------+
| x | 1 |
| y | 2 |
| NULL | NULL |
| | 0 | -- 'bad-value'
+-------+---------+
4 rows in set (0.00 sec)