Czy można zmienić listy ENUM ()?

19

Nie byłem pewien, czy zmiana listy ENUM () nie jest możliwa, więc zrobiłem test. W MySQL 5.1.58 stworzyłem testową tabelę InnoDB, która zawiera jedno pole o nazwie „bool” typu ENUM („tak”, „nie”).

Potem wykonałem ...

ALTER TABLE  `test`
CHANGE  `bool`  `bool` ENUM(  'yes',  'no',  'maybe' )
CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL

... i zadziałało.

Czy zrobiłem coś złego? Czy to zależy od silnika db?
Dlaczego wszyscy mówią, że zmiana listy ENUM () nie jest możliwa? na przykład. tutaj http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/

Aalex Gabi
źródło
3
Wspomniany artykuł nie mówi, że jest to niemożliwe; mówi, że zmiana listy członków jest kosztowna, ponieważ silnik wykonuje pełne skanowanie tabeli.
a1ex07
W październiku wspominałem o twoim linku na temat ENUM ( dba.stackexchange.com/a/6966/877 ). Dodatkowo zamieściłem referencje, jak to zrobić w MyISAM ( dba.stackexchange.com/a/6548/877 ). InnoDB nie wchodzi w rachubę w tym przypadku.
RolandoMySQLDBA

Odpowiedzi:

14

Dopóki stół jest pusty, nie ma problemu. Tak długo, jak dodawane są nowe wartości ENUM i nie zmienia się ich nazwy w zapełnionej tabeli, znowu nie ma problemu.

ENUM, który przedefiniowałeś w swoim pytaniu, zachował oryginalne wartości wewnętrzne dla tak i nie, gdy tabela testowa go zapamiętała.

Poniższe zasady dotyczą zapełnianych tabel:

A co z tym?

ALTER TABLE  `test`
CHANGE  `bool`  `bool` ENUM(  'no',  'yes',  'maybe' )
CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL

Teraz masz problem. Wartości ENUM we w pełni wypełnionej tabeli zostałyby odwrócone, dlatego tak jest teraz nie, a nie jest teraz tak.

A co z tym?

ALTER TABLE  `test`
CHANGE  `bool`  `bool` ENUM(  'maybe', 'no',  'yes' )
CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL

Wielki problem. W zapełnionej tabeli może tak jest teraz. Nowe wiersze wstawione z tak są odłączone od poprzednich wierszy tak, ponieważ teraz oznaczają być może.

STRESZCZENIE

Istnieją bardzo ryzykowne techniki przynęty i zamiany, aby zrobić to bardzo szybko w MyISAM . Zdecydowanie odradzam to robić w InnoDB ze względu na interakcję identyfikatora obszaru tabel z ibdata1.

RolandoMySQLDBA
źródło
Zatem wewnętrznie są one przechowywane jako int na podstawie kolejności w ENUM (). Na przykład ENUM („tak”, „nie”, „może”) przechowuje wewnętrznie 0 dla „tak”, 1 dla „nie”, 2 dla „być może”. Wyobrażam sobie, że metadane tabeli są podobne do ENUM („tak”, „nie”, „może”) zamiast ENUM („tak” => 0, „nie” => 1, „może” => 2). Czy to prawda?
Aalex Gabi
ENUM są ciągami, a nie liczbami całkowitymi: dev.mysql.com/doc/refman/5.0/en/enum.html
RolandoMySQLDBA
Zgadzam się, że ENUM są łańcuchami, ale wewnętrznie nie są ani przechowywane, ponieważ są łańcuchami, prawda?
Aalex Gabi
1
Masz w tym rację. W linku, który podałem, jest mapowanie ciągu na liczbę całkowitą jako metadane. Poszukaj tego wyrażenia: For example, a column specified as ENUM('one', 'two', 'three') can have any of the values shown here. The index of each value is also shown.a mapa wartości / indeksu jest konceptualizowana. Zatem w tabeli znajdowałaby się wartość ENUM związana z wewnętrznym numerem indeksu. Zmiana kolejności ciągów spowoduje zmianę kolejności indeksowania metadanych. Nie wróży to dobrze zapełnionej tabeli podczas redefiniowania ENUM.
RolandoMySQLDBA
2
Przynajmniej w przypadku MariaDB / InnoDB mogę powiedzieć, że to już nie jest ważne. Zmieniając środek ENUM, o ile nie ma rekordów z wartościami usuwanymi / zmienianymi, pozostałe wartości powinny pozostać takie, jakie są. Jedyną zaletą jest to, że musi odbudować stół.
Nuno