Tôi có thể đổi tên các giá trị trong cột MySQL ENUM trong một truy vấn không?


12

Giả sử tôi có một bảng cơ sở dữ liệu với một ENUM('value_one','value_two'). Tôi muốn thay đổi điều đó thành một ENUM('First value','Second value'). Tôi hiện đang làm điều đó như sau:

ALTER TABLE `table` MODIFY `column` ENUM('value_one','value_two','First value','Second value');
UPDATE `table` SET `column`='First Value' WHERE `column`='value_one';
UPDATE `table` SET `column`='Second Value' WHERE `column`='value_two';
ALTER TABLE `table` MODIFY `column` ENUM('First value','Second value');

Có cách nào hiệu quả hơn để làm điều này, EG một cách để thực hiện điều này với một đơn ALTER TABLE tuyên bố?

Câu trả lời:


10

Kỹ thuật follolwing tôi sắp chỉ ra cho bạn sẽ yêu cầu sự can đảm của thép.

Đưa ra các tiêu chí sau

  • datadir là /var/lib/mysql
  • cái bàn là mydb.mytb
  • cột enum được gọi là enum_col
  • động cơ là MyISAM

Đây là một vết nứt chết người:

  1. CREATE TABLE mydb.mybt LIKE mydb.mytb;

  2. ALTER TABLE mydb.mybt MODIFY enum_col ENUM('First value','Second value');

  3. SET wait_timeout=86400; SET interactive_timeout=86400;

  4. FLUSH TABLES WITH READ LOCK;

  5. Trong Phiên OS / SSH riêng, trao đổi các tệp .frm

    • $ mv /var/lib/mysql/mydb/mytb.frm /var/lib/mysql/mydb/myxx.frm
    • $ mv /var/lib/mysql/mydb/mybt.frm /var/lib/mysql/mydb/mytb.frm
    • $ mv /var/lib/mysql/mydb/myxx.frm /var/lib/mysql/mydb/mybt.frm
  6. UNLOCK TABLES;

  7. DROP TABLE mydb.mybt;

Đó là nó !!!

CAVEAT: TÔI KHÔNG THỂ KIẾM TIỀN TÍN DỤNG NÀY!

Kỹ thuật này xuất phát từ "MySQL hiệu suất cao: Tối ưu hóa, sao lưu, sao chép và hơn thế nữa", các trang 146-148 trong mục Subinging Speeding Up ALTER TABLE . Trang 1 Đoạn 1 nói:

Kỹ thuật chúng tôi sắp trình diễn là không được hỗ trợ, không có giấy tờ và có thể không hoạt động. Sử dụng nó có nguy cơ. Chúng tôi khuyên bạn sao lưu dữ liệu trước!

Hãy thử một lần ! (Xin vui lòng cho chúng tôi biết làm thế nào nó bật ra)

CẬP NHẬT 2011-10-05 17:49 EDT

Nếu bảng là MyISAM và bạn có đủ không gian trong sản xuất và cửa sổ thời gian chết thẳng, hãy thử điều này:

  1. service mysql restart --skip-networking

  2. Trong Phiên OS / SSH riêng, tạo một bản sao của bảng

    • cp /var/lib/mysql/mydb/mytb.frm /var/lib/mysql/mydb/mytbplay.frm
    • cp /var/lib/mysql/mydb/mytb.MYD /var/lib/mysql/mydb/mytbplay.MYD
    • cp /var/lib/mysql/mydb/mytb.MYI /var/lib/mysql/mydb/mytbplay.MYI

INFORMATION_SCHEMA.TABLESsẽ tự động phát hiện sự hiện diện của bảng mới được gọi mydb.mytbplay.

  1. Thực hiện thuật toán ruột thép trên mydb.mytbplay

  2. Bạn kiểm tra tính toàn vẹn của mydb.mytbplay

Nếu bạn hài lòng

  1. ALTER TABLE mydb.mytb RENAME mydb.mytb_backup;

  2. ALTER TABLE mydb.mytbplay RENAME mydb.mytb;

  3. service mysql restart

Hãy thử một lần!


+1 cho câu trả lời khéo léo! Tuy nhiên, tôi sẽ không thử và cho bạn biết nó diễn ra như thế nào khi câu hỏi đề cập đến một kịch bản nâng cấp cho tất cả các cơ sở dữ liệu sản xuất trực tiếp của khách hàng của tôi ;-) Tuy nhiên, tôi có thể thử điều này trên môi trường phát triển cho vui. Nhưng với cảnh báo đó, tôi sẽ không bao giờ chạy nó trong sản xuất!
Josh

3

Một giải pháp đơn giản sẽ là:

1- thêm một cột mới:

ALTER TABLE `table` ADD `enum2` ENUM('First value', 'Second value') NOT NULL AFTER `enum`;

2- Sao chép giá trị của cột vào enum2 bằng các thay thế:

UPDATE `table` SET enum2=REPLACE(`column`, "value_one", "new value")

3- Thả cột column, đổi tên enumthành column.

LƯU Ý : câu hỏi này trở lại 2011-10-05, giải pháp của tôi hợp lệ cho MYSQL 4.1 và mới hơn (AFAIK)


Mặc dù điều này nghe có vẻ là một giải pháp tốt (và gần như không gây căng thẳng như câu trả lời được chấp nhận!), Đáng chú ý là bước 3 không yêu cầu ít nhất một ALTER TABLEtuyên bố và OP đang tìm kiếm thứ gì đó chỉ yêu cầu một câu. Một lần nữa, điều đó nói rằng, nó có vẻ như là một giải pháp hoàn hảo, tiêu chuẩn.
RDFozz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.