MySQL
ENUM
Szukaj…
Dlaczego ENUM?
ENUM zapewnia sposób na podanie atrybutu dla wiersza. Atrybuty z małą liczbą opcji nienumerycznych działają najlepiej. Przykłady:
reply ENUM('yes', 'no')
gender ENUM('male', 'female', 'other', 'decline-to-state')
Wartości są łańcuchami:
INSERT ... VALUES ('yes', 'female')
SELECT ... --> yes female
TINYINT jako alternatywa
Powiedzmy, że mamy
type ENUM('fish','mammal','bird')
Alternatywą jest
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
który jest bardzo podobny do stołu wielu do wielu.
Porównanie i lepsze lub gorsze od ENUM:
- (gorzej) WSTAW: trzeba wyszukać
type
- (gorzej) WYBIERZ: musisz DOŁĄCZYĆ, aby uzyskać ciąg (ENUM daje ciąg bez wysiłku)
- (lepiej) Dodawanie nowych typów: Po prostu wstaw do tej tabeli. Z ENUM musisz zrobić ALTER TABLE.
- (to samo) Każda technika (dla maksymalnie 255 wartości) zajmuje tylko 1 bajt.
- (mieszane) Istnieje również problem integralności danych:
TINYINT
zaakceptuje nieprawidłowe wartości; podczas gdyENUM
ustawia je na specjalną wartość pustego ciągu (chyba że włączony jest tryb ścisłego SQL, w którym to przypadku są one odrzucane). Lepszą integralność danych można osiągnąć za pomocąTINYINT
, przekształcając go w klucz obcy w tablicę przeglądową: która przy odpowiednich zapytaniach / połączeniach, ale nadal istnieje niewielki koszt dotarcia do drugiej tabeli. (FOREIGN KEYs
nie są bezpłatne.)
VARCHAR jako alternatywa
Powiedzmy, że mamy
type ENUM('fish','mammal','bird')
Alternatywą jest
type VARCHAR(20) COMENT "fish, bird, etc"
Jest to dość otwarte, ponieważ nowe typy są dodawane w sposób trywialny.
Porównanie i lepsze lub gorsze od ENUM:
- (same) WSTAW: po prostu podaj ciąg
- (gorzej?) W INSERT literówka pozostanie niezauważona
- (to samo) WYBIERZ: zwracany jest aktualny ciąg
- (gorzej) Zużywa się znacznie więcej miejsca
Dodanie nowej opcji
ALTER TABLE tbl MODIFY COLUMN type ENUM('fish','mammal','bird','insect');
Notatki
- Podobnie jak we wszystkich przypadkach MODIFY COLUMN, musisz dołączyć
NOT NULL
i wszelkie inne kwalifikatory, które pierwotnie istniały, w przeciwnym razie zostaną utracone. - Jeśli dodasz na końcu listy, a lista zawiera mniej niż 256 elementów,
ALTER
następuje po prostu poprzez zmianę schematu. Oznacza to, że nie będzie długiej kopii tabeli. (Stare wersje MySQL nie miały tej optymalizacji).
NULL vs NOT NULL
Przykłady tego, co dzieje się, gdy wartości NULL i „zła wartość” są przechowywane w kolumnach zerowalnych, a nie zerowalnych. Pokazuje także użycie rzutowania na numeryczne za pomocą +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)
Co znajduje się w tabeli po tych wstawkach. Używa „+0” do rzutowania na numeryczne, aby zobaczyć, co jest przechowywane.
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)