เป็นไปได้ไหมที่จะเปลี่ยนรายการ ENUM ()


19

ฉันไม่แน่ใจว่าการเปลี่ยนรายการ ENUM () เป็นไปไม่ได้ดังนั้นฉันจึงทำการทดสอบ ใน MySQL v5.1.58 ฉันได้ทำการทดสอบตาราง InnoDB ที่มีหนึ่งฟิลด์ที่เรียกว่า 'บูล' ของประเภท ENUM ('ใช่', 'ไม่')

จากนั้นฉันก็ประหาร ...

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

... และมันก็ใช้งานได้

ฉันทำอะไรผิดหรือเปล่า? มันขึ้นอยู่กับเครื่องยนต์ db หรือไม่?
ทำไมทุกคนบอกว่าไม่สามารถเปลี่ยนรายการ ENUM () เช่น. ที่นี่http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/ที่นี่


3
บทความที่คุณกล่าวถึงไม่ได้บอกว่าเป็นไปไม่ได้ มันบอกว่าการเปลี่ยนรายชื่อสมาชิกนั้นแพงเพราะเอ็นจิ้นทำการสแกนเต็มตาราง
a1ex07

ฉันพูดถึงลิงก์ของคุณในเดือนตุลาคมเกี่ยวกับENUMs ( dba.stackexchange.com/a/6966/877 ) นอกจากนี้ฉันโพสต์ข้อมูลอ้างอิงเกี่ยวกับวิธีการทำเช่นนี้ใน MyISAM ( dba.stackexchange.com/a/6548/877 ) InnoDB เป็นคำถามที่ไม่เหมาะสมในกรณีนี้
RolandoMySQLDBA

คำตอบ:


14

ตราบใดที่ตารางยังว่างอยู่ก็จะไม่มีปัญหา ตราบใดที่ค่าใหม่สำหรับ ENUM ถูกต่อท้ายและไม่ได้เปลี่ยนชื่อให้กับตารางที่มีประชากรก็ไม่มีปัญหาอีกต่อไป

ENUM ที่คุณกำหนดใหม่ในคำถามของคุณจะเก็บค่าภายในดั้งเดิมไว้สำหรับใช่และไม่ใช่ตามตารางการทดสอบล่าสุดที่จำได้

ข้อมูลต่อไปนี้ใช้กับตารางที่มีประชากร:

แล้วเรื่องนี้ล่ะ

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

ตอนนี้คุณมีปัญหา ค่า ENUM ในตารางที่มีประชากรเต็มจะทำให้ค่าภายในของพวกเขากลับด้านดังนั้นใช่ตอนนี้ไม่ใช่และไม่ใช่ตอนนี้ใช่

แล้วเรื่องนี้ล่ะ

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

ปัญหาใหญ่. ในตารางที่มีประชากรใช่ตอนนี้อาจจะเป็น แถวใหม่ที่แทรกด้วยใช่จะถูกตัดการเชื่อมต่อจากแถวใช่ก่อนหน้านี้เพราะตอนนี้พวกเขาอาจหมายถึง

สรุป

มีมากมีความเสี่ยงสูงเทคนิคเหยื่อและสวิทช์ที่จะทำเช่นนี้ได้อย่างรวดเร็วใน MyISAM ฉันขอแนะนำอย่างยิ่งให้ไม่ทำสิ่งนี้ใน InnoDB เพราะการโต้ตอบกับ tablespace id id ของมันกับ ibdata1


ดังนั้นภายในเหล่านั้นจะถูกเก็บไว้เป็น int ตามลำดับใน ENUM () ตัวอย่างเช่น ENUM ('ใช่', 'ไม่', 'อาจจะ') เก็บภายใน 0 สำหรับ 'ใช่', 1 สำหรับ 'ไม่', 2 สำหรับ 'อาจจะ' ฉันจินตนาการว่าข้อมูลเมตาของตารางเป็นเหมือน ENUM ('ใช่', 'ไม่', 'อาจจะ') แทนที่จะเป็น ENUM ('ใช่' => 0, 'ไม่' => 1, 'อาจ' => 2) จริงป้ะ?
Aalex Gabi

ENUMs เป็นสตริงที่ไม่ใช่จำนวนเต็ม: dev.mysql.com/doc/refman/5.0/en/enum.html
RolandoMySQLDBA

ฉันเห็นด้วย Enum เป็นสตริง แต่ภายในเหล่านั้นจะไม่ถูกเก็บไว้เป็นสตริงใช่ไหม
Aalex Gabi

1
คุณถูกต้องในเรื่องนี้ ในลิงก์ที่ฉันให้ไว้จะมีการจับคู่สตริงกับจำนวนเต็มเป็นเมทาดาทา มองหาวลีนี้: 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.และแผนที่ค่า / ดัชนีเป็นแนวคิด ดังนั้นจะมีค่า ENUM ในตารางที่เชื่อมโยงกับหมายเลขดัชนีภายใน การจัดเรียงสตริงใหม่จะจัดเรียงการทำดัชนีข้อมูลเมตา สิ่งนี้ไม่เป็นลางดีสำหรับตารางที่มีประชากรเมื่อทำการกำหนด ENUM ใหม่
RolandoMySQLDBA

2
อย่างน้อยสำหรับ MariaDB / InnoDB ฉันสามารถบอกได้ว่านี่ไม่ถูกต้องอีกต่อไป การเปลี่ยนจุดกึ่งกลางของ ENUM ตราบใดที่ไม่มีเร็กคอร์ดที่มีค่าที่ถูกลบ / เปลี่ยนแปลงค่าอื่น ๆ ก็ควรคงอยู่เหมือนเดิม ข้อดีอย่างเดียวคือมันต้องสร้างตารางใหม่
Nuno
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.