Apakah mungkin untuk mengubah daftar ENUM ()?

19

Saya tidak yakin apakah mengubah daftar ENUM () tidak mungkin jadi saya membuat tes. Di MySQL v5.1.58 saya membuat tabel InnoDB uji yang berisi satu bidang yang disebut 'bool' dari tipe ENUM ('ya', 'tidak').

Lalu aku mengeksekusi ...

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

... dan berhasil.

Apakah saya melakukan kesalahan? Apakah ini tergantung pada mesin db?
Mengapa semua orang mengatakan bahwa mengubah daftar ENUM () tidak mungkin? misalnya. di sini http://komlenic.com/244/8-reason-why-mysqls-enum-data-type-is-evil/

Aalex Gabi
sumber
3
Artikel yang Anda sebutkan tidak mengatakan itu tidak mungkin; ia mengatakan bahwa mengubah daftar anggota itu mahal karena mesin melakukan pemindaian tabel penuh.
a1ex07
Saya menyebutkan tautan Anda kembali pada bulan Oktober tentang ENUM ( dba.stackexchange.com/a/6966/877 ). Selain itu, saya memposting referensi tentang bagaimana melakukan ini di MyISAM ( dba.stackexchange.com/a/6548/877 ). InnoDB keluar dari pertanyaan dalam hal ini.
RolandoMySQLDBA

Jawaban:

14

Selama meja kosong, tidak ada masalah. Selama nilai-nilai baru untuk ENUM ditambahkan dan tidak diganti diberi tabel yang diisi, sekali lagi tidak ada masalah.

ENUM yang Anda definisikan ulang dalam pertanyaan Anda benar-benar menyimpan nilai internal asli untuk ya dan tidak sebagaimana tabel tes terakhir mengingatnya.

Hal berikut ini berlaku untuk tabel terisi:

Bagaimana dengan ini?

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

Sekarang kamu punya masalah. Nilai-nilai ENUM dalam tabel yang terisi penuh akan memiliki nilai internal mereka terbalik sehingga ya sekarang tidak dan tidak sekarang ya.

Bagaimana dengan ini?

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

Masalah besar. Dalam tabel yang padat, ya sekarang mungkin. Baris baru yang disisipkan dengan yes terputus dari baris ya sebelumnya karena sekarang berarti mungkin.

RINGKASAN

Ada teknik-teknik umpan-dan-saklar yang sangat berisiko tinggi untuk melakukan ini dengan sangat cepat di MyISAM . Saya akan sangat menyarankan untuk tidak melakukan ini di InnoDB karena interaksi tablespace id dengan ibdata1.

RolandoMySQLDBA
sumber
Jadi secara internal mereka disimpan sebagai int berdasarkan urutan dalam ENUM (). Misalnya ENUM ('ya', 'tidak', 'mungkin') menyimpan secara internal 0 untuk 'ya', 1 untuk 'tidak', 2 untuk 'mungkin'. Saya membayangkan bahwa metadata tabel seperti ENUM ('ya', 'tidak', 'mungkin') alih-alih ENUM ('ya' => 0, 'tidak' => 1, 'mungkin' => 2). Apakah itu benar
Aalex Gabi
ENUM adalah string bukan bilangan bulat: dev.mysql.com/doc/refman/5.0/en/enum.html
RolandoMySQLDBA
Saya setuju ENUM adalah string tetapi secara internal itu tidak disimpan sebagai string bukan?
Aalex Gabi
1
Anda benar dalam hal ini. Di tautan yang saya berikan, ada pemetaan string ke integer sebagai metadata. Cari frasa ini: 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.dan peta nilai / indeks dikonseptualisasikan. Dengan demikian, akan ada nilai ENUM dalam tabel yang terkait dengan nomor indeks internal. Mengatur ulang string akan mengatur ulang pengindeksan metadata. Ini bukan pertanda baik untuk tabel yang diisi saat mendefinisikan ulang ENUM.
RolandoMySQLDBA
2
Setidaknya untuk MariaDB / InnoDB, saya tahu ini tidak valid lagi. Mengubah tengah ENUM, selama tidak ada catatan dengan nilai yang dihapus / diubah, nilai-nilai lain harus tetap seperti semula. Satu-satunya keuntungan adalah harus membangun kembali tabel.
Nuno