Est-il possible de modifier les listes ENUM ()?

19

Je ne savais pas si changer la liste ENUM () n'était pas possible, j'ai donc fait un test. Dans MySQL v5.1.58, j'ai fait une table de test InnoDB qui contient un champ appelé 'bool' de type ENUM ('oui', 'non').

Puis j'ai exécuté ...

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

... et ça a marché.

Ai-je fait quelque chose de mal? Dépend-il du moteur db?
Pourquoi tout le monde dit que changer une liste ENUM () n'est pas possible? par exemple. ici http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/

Aalex Gabi
la source
3
L'article que vous avez mentionné ne dit pas que c'est impossible; il indique que la modification de la liste des membres coûte cher car le moteur effectue une analyse complète de la table.
a1ex07
J'ai mentionné votre lien en octobre sur les ENUM ( dba.stackexchange.com/a/6966/877 ). De plus, j'ai publié une référence sur la façon de procéder dans MyISAM ( dba.stackexchange.com/a/6548/877 ). InnoDB est hors de question dans ce cas.
RolandoMySQLDBA

Réponses:

14

Tant que la table est vide, il n'y a pas de problème. Tant que de nouvelles valeurs pour ENUM sont ajoutées et non renommées étant donné une table remplie, là encore aucun problème.

L'ENUM que vous avez redéfini dans votre question a en fait conservé les valeurs internes d'origine pour oui et non, comme le tableau de test s'en est souvenu en dernier.

Ce qui suit s'applique aux tables remplies:

Et ça?

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

Vous avez maintenant un problème. Les valeurs ENUM dans une table entièrement remplie auraient leurs valeurs internes inversées de sorte que oui est maintenant non et non est maintenant oui.

Et ça?

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

Gros problème. Dans une table peuplée, oui l'est peut-être maintenant. Les nouvelles lignes insérées avec oui sont déconnectées des lignes oui précédentes car elles signifient maintenant peut-être.

SOMMAIRE

Il existe des techniques d'appât et de changement à très haut risque pour le faire très rapidement dans MyISAM . Je déconseille fortement de faire cela dans InnoDB en raison de son interaction avec le tablespace id avec ibdata1.

RolandoMySQLDBA
la source
Donc, en interne, ceux-ci sont stockés sous forme d'int en fonction de l'ordre dans ENUM (). Par exemple, ENUM («oui», «non», «peut-être») stocke en interne 0 pour «oui», 1 pour «non», 2 pour «peut-être». J'imagine que les métadonnées de la table sont comme ENUM ('oui', 'non', 'peut-être') au lieu d'ENUM ('oui' => 0, 'non' => 1, 'peut-être' => 2). Est-ce vrai?
Aalex Gabi
Les ENUM sont des chaînes et non des entiers: dev.mysql.com/doc/refman/5.0/en/enum.html
RolandoMySQLDBA
Je suis d'accord que les ENUM sont des chaînes mais en interne celles-ci ne sont pas stockées sous forme de chaînes, n'est-ce pas?
Aalex Gabi
1
Vous avez raison. Dans le lien que j'ai fourni, il y a un mappage de chaîne en entier en tant que métadonnées. Recherchez cette phrase: 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.et la carte valeur / index est conceptualisée. Ainsi, il y aurait une valeur ENUM dans une table associée à un numéro d'index interne. Réorganiser les chaînes réorganisera l'indexation des métadonnées. Cela n'augure rien de bon pour une table remplie lors de la redéfinition d'un ENUM.
RolandoMySQLDBA du
2
Au moins pour MariaDB / InnoDB, je peux dire que ce n'est plus valable. Changer le milieu d'ENUM, tant qu'il n'y a pas d'enregistrements avec les valeurs supprimées / modifiées, les autres valeurs doivent rester telles quelles. Le seul avantage est qu'il doit reconstruire la table.
Nuno