MySQL
ENUM
Zoeken…
Waarom ENUM?
ENUM biedt een manier om een attribuut voor een rij te geven. Attributen met een klein aantal niet-numerieke opties werken het beste. Voorbeelden:
reply ENUM('yes', 'no')
gender ENUM('male', 'female', 'other', 'decline-to-state')
De waarden zijn tekenreeksen:
INSERT ... VALUES ('yes', 'female')
SELECT ... --> yes female
TINYINT als alternatief
Laten we zeggen dat we dat hebben gedaan
type ENUM('fish','mammal','bird')
Een alternatief is
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
die erg veel op een veel-op-veel-tafel lijkt.
Vergelijking, of beter of slechter dan ENUM:
- (erger) INSERT: moet het
type
opzoeken - (erger) SELECTEER: moet LID worden om de string te krijgen (ENUM geeft je de string zonder moeite)
- (beter) Nieuwe typen toevoegen: eenvoudig in deze tabel invoegen. Met ENUM moet u een ALTER TABEL doen.
- (hetzelfde) Beide technieken (voor maximaal 255 waarden) duren slechts 1 byte.
- (gemengd) Er is ook een probleem met gegevensintegriteit:
TINYINT
zal ongeldige waarden toelaten; terwijlENUM
deze op een speciale lege tekenreekswaarde instelt (tenzij de strikte SQL-modus is ingeschakeld, in welk geval ze worden afgewezen). Betere gegevensintegriteit kan worden bereikt metTINYINT
door er een externe sleutel van te maken in een opzoektabel: die, met de juiste query's / joins, maar er zijn nog steeds de kleine kosten voor het bereiken van de andere tabel. (FOREIGN KEYs
zijn niet gratis.)
VARCHAR als alternatief
Laten we zeggen dat we dat hebben gedaan
type ENUM('fish','mammal','bird')
Een alternatief is
type VARCHAR(20) COMENT "fish, bird, etc"
Dit heeft een vrij open einde doordat nieuwe typen triviaal worden toegevoegd.
Vergelijking, of beter of slechter dan ENUM:
- (zelfde) INVOEGEN: geef gewoon de string op
- (erger?) Bij INSERT blijft een typfout onopgemerkt
- (hetzelfde) SELECTEER: de werkelijke string wordt geretourneerd
- (erger) Er wordt veel meer ruimte verbruikt
Een nieuwe optie toevoegen
ALTER TABLE tbl MODIFY COLUMN type ENUM('fish','mammal','bird','insect');
Notes
- Zoals bij alle gevallen van KOLOM WIJZIGEN, moet u
NOT NULL
en alle andere kwalificaties die oorspronkelijk bestonden, anders gaan ze verloren. - Als u toevoegt aan het einde van de lijst en de lijst bestaat uit 256 items, wordt
ALTER
gedaan door alleen het schema te wijzigen. Dat wil zeggen dat er geen langdurig tabelexemplaar zal zijn. (Oude versies van MySQL hadden deze optimalisatie niet.)
NULL versus NIET NULL
Voorbeelden van wat er gebeurt wanneer NULL en 'bad-value' worden opgeslagen in nulbare en niet nulbare kolommen. Toont ook het gebruik van casting naar numeriek 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)
Wat staat er in de tabel na die inzetstukken. Dit gebruikt "+0" om naar numeriek te casten om te zien wat er is opgeslagen.
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)