É possível alterar as listas ENUM ()?

19

Eu não tinha certeza se a alteração da lista ENUM () não é possível, então fiz um teste. No MySQL v5.1.58, fiz uma tabela de teste do InnoDB que contém um campo chamado 'bool' do tipo ENUM ('yes', 'no').

Então eu executei ...

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

... e funcionou.

Eu fiz alguma coisa errada? É dependente do mecanismo db?
Por que todo mundo diz que alterar uma lista ENUM () não é possível? por exemplo. aqui http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/

Aalex Gabi
fonte
3
O artigo que você mencionou não diz que é impossível; ele diz que alterar a lista de membros é caro porque o mecanismo faz a varredura completa da tabela.
a1ex07
Mencionei seu link em outubro sobre ENUMs ( dba.stackexchange.com/a/6966/877 ). Além disso, publiquei uma referência sobre como fazer isso no MyISAM ( dba.stackexchange.com/a/6548/877 ). O InnoDB está fora de questão nesta instância.
RolandoMySQLDBA

Respostas:

14

Contanto que a tabela esteja vazia, não há problema. Desde que novos valores para ENUM sejam anexados e não renomeados, dada uma tabela preenchida, novamente não há problema.

O ENUM que você redefiniu na sua pergunta realmente manteve os valores internos originais de yes e no como a tabela de teste se lembrou pela última vez.

O seguinte se aplica às tabelas preenchidas:

E isso?

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

Agora você tem um problema. Os valores ENUM em uma tabela totalmente preenchida teriam seus valores internos revertidos para que sim agora não e agora não seja sim.

E isso?

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

Grande problema. Em uma tabela preenchida, sim é agora talvez. Novas linhas inseridas com yes são desconectadas das linhas yes anteriores porque agora significam talvez.

RESUMO

Existem técnicas de isca e troca de alto risco para fazer isso muito rapidamente no MyISAM . Eu não recomendaria isso no InnoDB por causa de sua interação de identificação do espaço de tabela com o ibdata1.

RolandoMySQLDBA
fonte
Portanto, internamente, esses são armazenados como int com base na ordem em ENUM (). Por exemplo, ENUM ('yes', 'no', 'maybe') armazena internamente 0 para 'yes', 1 para 'no', 2 para 'maybe'. Eu imagino que os metadados da tabela sejam como ENUM ('yes', 'no', 'maybe') em vez de ENUM ('yes' => 0, 'no' => 1, 'maybe' => 2). É verdade?
Aalex Gabi
ENUMs não são números inteiros: dev.mysql.com/doc/refman/5.0/en/enum.html
RolandoMySQLDBA
Eu concordo ENUMs são strings, mas internamente elas não são armazenadas como strings, não é?
Aalex Gabi
11
Você está correto nisso. No link que forneci, há um mapeamento de string para número inteiro como metadados. Procure esta frase: 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.e o mapa de valor / índice é conceitualizado. Portanto, haveria um valor ENUM em uma tabela associada ao número do índice interno. Reorganizar as strings reorganizará a indexação de metadados. Isso não é um bom presságio para uma tabela preenchida ao redefinir um ENUM.
RolandoMySQLDBA
2
Pelo menos para MariaDB / InnoDB, posso dizer que isso não é mais válido. Alterando o meio de ENUM, desde que não haja registros com os valores sendo removidos / alterados, os outros valores devem permanecer como estão. A única vantagem é que ele precisa reconstruir a tabela.
Nuno