Làm cách nào để thêm nhiều thành viên vào cột loại ENUM của tôi trong MySQL?


157

Hướng dẫn tham khảo MySQL không cung cấp một ví dụ rõ ràng về cách thực hiện việc này.

Tôi có một cột loại ENUM của tên quốc gia mà tôi cần thêm nhiều quốc gia hơn. Cú pháp MySQL chính xác để đạt được điều này là gì?

Đây là nỗ lực của tôi:

ALTER TABLE carmake CHANGE country country ENUM('Sweden','Malaysia');

Lỗi tôi nhận được là: ERROR 1265 (01000): Data truncated for column 'country' at row 1.

Các countrycột là ENUM kiểu cột trong-tuyên bố trên.

HIỂN THỊ TẠO RA BẢNG ĐẦU RA:

mysql> SHOW CREATE TABLE carmake;
+---------+---------------------------------------------------------------------+
| Table   | Create Table
+---------+---------------------------------------------------------------------+
| carmake | CREATE TABLE `carmake` (
`carmake_id` tinyint(4) NOT NULL AUTO_INCREMENT,
`name` tinytext,
`country` enum('Japan','USA','England','Australia','Germany','France','Italy','Spain','Czech Republic','China','South Korea','India') DEFAULT NULL,
PRIMARY KEY (`carmake_id`),
KEY `name` (`name`(3))
) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=latin1 |
+---------+---------------------------------------------------------------------+
1 row in set (0.00 sec)

CHỌN quốc gia DISTINCT TỪ đầu ra carmake :

+----------------+
| country        |
+----------------+
| Italy          |
| Germany        |
| England        |
| USA            |
| France         |
| South Korea    |
| NULL           |
| Australia      |
| Spain          |
| Czech Republic |
+----------------+

Câu trả lời:


134
ALTER TABLE
    `table_name`
MODIFY COLUMN
    `column_name2` enum(
        'existing_value1',
        'existing_value2',
        'new_value1',
        'new_value2'
    )
NOT NULL AFTER `column_name1`;

7
Hầu hết các lệnh ALTER TABLE sẽ viết lại hoàn toàn toàn bộ bảng. Là mys đủ thông minh để không làm điều đó với enum?
Giăng

enum chỉ là một số nguyên ưa thích, với một chuỗi đại diện. thêm các mục vào cuối là tốt, vì bạn chỉ cần thêm các giá trị cũ. nhưng việc thay đổi thứ tự / loại bỏ enums sẽ làm cho những con số đó không được xác định. (ví dụ: 1 => italy, 2 => đức), sau đó kéo dài sẽ là (1 => italy, 2 => đức, 3 => sweenden).
lintabá

1
@ John phụ thuộc. Đối với MariaDB, việc thêm các giá trị mới vào cuối enum có thể được thực hiện inplacekể từ 10.3.7: mariadb.com/kb/en/l Library / trộm
Felipe Philipp

99

Mã của bạn làm việc cho tôi. Đây là trường hợp thử nghiệm của tôi:

mysql> CREATE TABLE carmake (country ENUM('Canada', 'United States'));
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW CREATE TABLE carmake;
+---------+-------------------------------------------------------------------------------------------------------------------------+
| Table   | Create Table                                                                                                            |
+---------+-------------------------------------------------------------------------------------------------------------------------+
| carmake | CREATE TABLE `carmake` (
  `country` enum('Canada','United States') default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
+---------+-------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> ALTER TABLE carmake CHANGE country country ENUM('Sweden','Malaysia');
Query OK, 0 rows affected (0.53 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> SHOW CREATE TABLE carmake;
+---------+--------------------------------------------------------------------------------------------------------------------+
| Table   | Create Table                                                                                                       |
+---------+--------------------------------------------------------------------------------------------------------------------+
| carmake | CREATE TABLE `carmake` (
  `country` enum('Sweden','Malaysia') default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
+---------+--------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

Bạn đang nhìn thấy lỗi gì?

FWIW này cũng sẽ hoạt động:

ALTER TABLE carmake MODIFY COLUMN country ENUM('Sweden','Malaysia');

Tôi thực sự muốn giới thiệu một bảng quốc gia chứ không phải cột enum. Bạn có thể có hàng trăm quốc gia sẽ tạo ra một enum khá lớn và vụng về.

EDIT: Bây giờ tôi có thể thấy thông báo lỗi của bạn:

ERROR 1265 (01000): Data truncated for column 'country' at row 1.

Tôi nghi ngờ bạn có một số giá trị trong cột quốc gia của bạn không xuất hiện trong ENUM. Đầu ra của lệnh sau là gì?

SELECT DISTINCT country FROM carmake;

KHÁC EDIT: Đầu ra của lệnh sau là gì?

SHOW VARIABLES LIKE 'sql_mode';

Là nó STRICT_TRANS_TABLEShay STRICT_ALL_TABLES? Điều đó có thể dẫn đến một lỗi, thay vì cảnh báo thông thường mà MySQL sẽ đưa ra cho bạn trong tình huống này.

YET ANOTHER EDIT: Ok, bây giờ tôi thấy rằng bạn chắc chắn có các giá trị trong bảng không có trong bảng mới ENUM. ENUMĐịnh nghĩa mới chỉ cho phép 'Sweden''Malaysia'. Bảng có 'USA', 'India'và một số người khác.

LAST EDIT (MAYBE): Tôi nghĩ bạn đang cố gắng làm điều này:

ALTER TABLE carmake CHANGE country country ENUM('Italy', 'Germany', 'England', 'USA', 'France', 'South Korea', 'Australia', 'Spain', 'Czech Republic', 'Sweden', 'Malaysia') DEFAULT NULL;

Có nhiều hơn một cột trong carmakebảng của tôi . Điều đó có thể có bất cứ điều gì để làm với nó?
Zaid

1
@Zaid hãy cẩn thận khi nói điều đó. MySQL nổi tiếng là cho phép rác vào các cột ENUM. Nó sẽ âm thầm chuyển đổi các giá trị không phù hợp thành các chuỗi trống, ví dụ. Bạn có chắc chắn 100% rằng bạn không có bất kỳ giá trị vi phạm nào không? Không có chuỗi trống? Không có khoảng trắng hàng đầu hoặc dấu? Trường hợp khác nhau? Ký tự có dấu?
Asaph

1
@Zaid Tôi nghĩ bạn có các giá trị trong bảng mà không có trong định nghĩa ENUM được cập nhật của bạn. Định nghĩa mới của bạn chỉ cho phép Thụy Điển và Malaysia. Bảng của bạn có Hoa Kỳ, Ấn Độ, Đức ... Không có giá trị nào trong số đó sẽ được phép trong ENUM mới của bạn. Nếu những gì bạn đang cố gắng làm là thêm Thụy Điển và Malaysia trong khi duy trì các thành viên ban đầu của ENUM, bạn sẽ cần phải giữ lại tất cả các giá trị ENUM ban đầu cộng với 2 giá trị mới trong câu lệnh ALTER của bạn.
Asaph

2
@Zaid Bạn được chào đón. Nếu bạn sử dụng bảng quốc gia có khóa ngoại thay vì ENUM như tôi đã đề xuất sớm, bạn sẽ có thể chỉ cần thêm hàng cho các quốc gia mới. BTW: Nếu bạn thấy các đề xuất của tôi hữu ích, vui lòng đánh dấu câu trả lời của tôi chính xác :)
Asaph

3
-1 Vì không rõ ràng về những gì giải pháp thực tế ở đây. Có quá nhiều cuộc trò chuyện và rất nhiều "thử cái này, ồ, hãy thử cái này thay thế." Câu trả lời ban đầu thậm chí không trả lời câu hỏi thực tế của OP - mãi đến sau này bạn mới nhận ra vấn đề là gì, và sau đó bạn đi vào các mẫu mã đơn giản không thực sự có ý nghĩa gì với người đang tìm câu hỏi / câu trả lời này một thời gian sau Bối cảnh của các chỉnh sửa của bạn là / là tạm thời và không còn rõ ràng nữa.
Jim Rubenstein

73

Cuộc thảo luận mà tôi có với Asaph có thể không rõ ràng để theo dõi khi chúng tôi qua lại khá nhiều.

Tôi nghĩ rằng tôi có thể làm rõ kết quả của bài diễn văn của chúng tôi cho những người khác có thể gặp phải tình huống tương tự trong tương lai để hưởng lợi từ:

ENUMcột -type là những con thú rất khó thao tác. Tôi muốn thêm hai quốc gia (Malaysia và Thụy Điển) vào nhóm quốc gia hiện có trong ENUM của tôi.

Có vẻ như MySQL 5.1 (là thứ tôi đang chạy) chỉ có thể cập nhật ENUM bằng cách xác định lại bộ hiện có bên cạnh những gì tôi muốn:

Điều này đã không làm việc:

ALTER TABLE carmake CHANGE country country ENUM('Sweden','Malaysia') DEFAULT NULL;

Lý do là các tuyên bố MySQL đã được thay thế ENUM hiện với một chứa các mục 'Malaysia''Sweden'chỉ. MySQL đã đưa ra một lỗi vì carmakebảng đã có các giá trị như 'England''USA'đó không phải là một phần của ENUMđịnh nghĩa mới.

Đáng ngạc nhiên, những điều sau đây cũng không hoạt động:

ALTER TABLE carmake CHANGE country country ENUM('Australia','England','USA'...'Sweden','Malaysia') DEFAULT NULL;

Nó chỉ ra rằng ngay cả thứ tự các yếu tố của các ENUMnhu cầu hiện có cần được bảo tồn trong khi thêm thành viên mới vào nó. Vì vậy, nếu cái hiện tại của tôi ENUMtrông giống như vậy ENUM('England','USA'), thì cái mới của tôi ENUMphải được định nghĩa ENUM('England','USA','Sweden','Malaysia')và không ENUM('USA','England','Sweden','Malaysia'). Vấn đề này chỉ trở nên rõ ràng khi có các bản ghi trong bảng hiện có sử dụng 'USA'hoặc 'England'các giá trị.

LINE BOTTOM:

Chỉ sử dụng ENUMs khi bạn không mong đợi nhóm thành viên của mình thay đổi sau khi được xác định. Mặt khác, bảng tra cứu dễ dàng hơn để cập nhật và sửa đổi.


Tôi sẽ mạo hiểm một điểm mấu chốt mạnh mẽ hơn ... "chỉ sử dụng ENUM khi bạn hoàn toàn chắc chắn 100% rằng các giá trị sẽ không bao giờ thay đổi". Nếu một bảng phát triển lớn, sẽ là một nỗi đau nếu bạn phải thay đổi những giá trị đó.
DougW

6
Tôi không chắc là tôi đồng ý với điểm mấu chốt đó. Tin tôi đi Tôi không thích ENUM chút nào nhưng tôi không thấy nguy hiểm khi THÊM vào ENUM có thể. ENUM là, ở cốt lõi của nó, ánh xạ 0 -> Tùy chọn 1, 1-> Tùy chọn 2, v.v. Thêm vào đó không nên gây ra sự cố.
JoshStrange

2
@JoshStrange Đó không phải là một mối nguy hiểm quá lớn, nó có thể là một sự bất tiện rất lớn khi thứ tự ENUM của bạn rất quan trọng (ví dụ: khi được sử dụng để đặt hàng).
1in9ui5t

1
Tôi nghĩ điều quan trọng cũng phải nói ở điểm mấu chốt là chỉ hợp lệ với các phiên bản kế thừa của MySQL bởi vì với những gì tôi hiểu, với những phiên bản mới hơn thì không có vấn đề gì.
Niccolò

Câu trả lời này không còn phù hợp nữa, câu trả lời dưới đây nên được đánh dấu là chấp nhận.
ofirski

16

Trong phiên bản máy chủ MYSQL: 5.0.27 tôi đã thử cái này và nó hoạt động tốt để tôi kiểm tra phiên bản của bạn

ALTER TABLE carmake
     MODIFY `country` ENUM('Japan', 'USA', 'England', 'Australia', 'Germany', 'France', 'Italy', 'Spain', 'Czech Republic', 'China', 'South Korea', 'India', 'Sweden', 'Malaysia');

1
Không chắc chắn tại sao điều này không được nâng cao hơn. Nó đơn giản, và nó làm việc cho tôi.
tổ tiên

1

FYI: Một công cụ mô phỏng hữu ích - phpMyAdmin với Wamperver 3.0.6 - Preview SQL: Tôi sử dụng 'Preview SQL' để xem mã SQL sẽ được tạo trước khi bạn lưu cột với thay đổi thành ENUM. Xem trước SQL

Ở trên bạn thấy rằng tôi đã nhập 'Ford', 'Toyota' vào ENUM nhưng tôi đang nhận cú pháp ENUM (0) đang tạo ra lỗi cú pháp Lỗi truy vấn 1064 #

Sau đó tôi sao chép và dán và thay đổi SQL và chạy nó thông qua SQL với kết quả khả quan.

SQL đã thay đổi

Đây là một quickfix mà tôi sử dụng thường xuyên và cũng có thể được sử dụng trên các giá trị ENUM hiện tại cần được thay đổi. Nghĩ rằng điều này có thể hữu ích.


1

Đây là một cách khác ...

Nó thêm "những người khác" vào định nghĩa enum của cột "rtipo" của bảng "Firmas".

set @new_enum = 'others';
set @table_name = 'firmas';
set @column_name = 'rtipo';
select column_type into @tmp from information_schema.columns 
  where table_name = @table_name and column_name=@column_name;
set @tmp = insert(@tmp, instr(@tmp,')'), 0, concat(',\'', @new_enum, '\'') );
set @tmp = concat('alter table ', @table_name, ' modify ', @column_name, ' ', @tmp);
prepare stmt from @tmp;
execute stmt;
deallocate prepare stmt;

-8

Điều đó là có thể nếu bạn tin tưởng. Hehe. thử mã này

public function add_new_enum($new_value)
  {
    $table="product";
    $column="category";
         $row = $this->db->query("SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_NAME = ? AND COLUMN_NAME = ?", array($table, $column))->row_array();

    $old_category = array();
    $new_category="";
    foreach (explode(',', str_replace("'", '', substr($row['COLUMN_TYPE'], 5, (strlen($row['COLUMN_TYPE']) - 6)))) as $val)
    {
        //getting the old category first

        $old_category[$val] = $val;
        $new_category.="'".$old_category[$val]."'".",";
    }

     //after the end of foreach, add the $new_value to $new_category

      $new_category.="'".$new_value."'";

    //Then alter the table column with the new enum

    $this->db->query("ALTER TABLE product CHANGE category category ENUM($new_category)");
  }

Trước khi thêm giá trị mới

Sau khi thêm giá trị mới


11
Tôi không thấy cách này mang lại bất cứ điều gì mới cho bàn. Câu hỏi hoàn toàn là từ quan điểm của MySQL. Câu trả lời của bạn kết hợp PHP ngẫu nhiên hoàn toàn không liên quan và bạn không cố gắng giải thích bất kỳ câu hỏi nào. Nguồn thông tin vô dụng
Jonathan
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.