Як додати більше членів до колонки типу ENUM у MySQL?


157

Довідковий посібник MySQL не дає чіткого прикладу того, як це зробити.

У мене є стовпець типу ENUM із назвами країн, до яких потрібно додати більше країн. Який правильний синтаксис MySQL для досягнення цього?

Ось моя спроба:

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

Я отримую помилку: ERROR 1265 (01000): Data truncated for column 'country' at row 1.

countryСтовпець є ENUM-типу в вищенаведеному заяві.

ПОКАЗУЙТЕ СТВОРИТИ ТАБЛИЧНИЙ ВИХІД:

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)

SELECT DISTINCT FROM країни carmake ВИХОДУ:

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

Відповіді:


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

7
Більшість команд ALTER TABLE повністю переписують всю таблицю. Чи достатньо розумний mysql, щоб не робити цього з перерахунком?
Іоанн

enum - це просто фантазійне ціле число з рядковим поданням. додавання елементів до кінця - це добре, оскільки ви просто додаєте значення старих значень. але зміна порядку / видалення перерахунків зробить ці цифри невизначеними. (наприклад, 1 => італія, 2 => німецька), тоді розширення буде (1 => італія, 2 => німецька, 3 => солодке).
lintabá

1
@John залежить. Для MariaDB додавання нових значень наприкінці перерахунків можна зробити inplaceз 10.3.7: mariadb.com/kb/en/library/…
Феліпе Філіпп,

99

Ваш код працює на мене. Ось мій тестовий випадок:

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)

Яку помилку ви бачите?

FWIW це також працює:

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

Я б фактично рекомендував таблицю країни, а не перерахунок стовпця. У вас можуть бути сотні країн, які могли б створити досить великий і незграбний перелік.

EDIT: Тепер, коли я бачу ваше повідомлення про помилку:

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

Я підозрюю, що у стовпці країни є деякі значення, які не відображаються у вашій країні ENUM. Яким є результат наступної команди?

SELECT DISTINCT country FROM carmake;

ДРУГИЙ РЕДАКТ: Що є результатом наступної команди?

SHOW VARIABLES LIKE 'sql_mode';

Це STRICT_TRANS_TABLESчи STRICT_ALL_TABLES? Це може призвести до помилки, а не звичайне попередження, яке надасть MySQL у цій ситуації.

ІНШИЙ РЕДАКТ: Ок, зараз я бачу, що у таблиці напевно є значення, які не в новій ENUM. Нове ENUMвизначення дозволяє лише 'Sweden'і 'Malaysia'. У таблиці є 'USA', 'India'і деякі інші.

ОСТАНА РЕДАКЦІЯ (МОЖЕ): Я думаю, ви намагаєтесь це зробити:

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

У моїй carmakeтаблиці більше одного стовпця . Чи може це мати щось спільне?
Заїд

1
@Zaid будьте обережні, щоб сказати це. MySQL відомий тим, що дозволяє сміття в ENUM стовпці. Наприклад, він мовчки перетворить невідповідні значення в порожні рядки. Ви на 100% впевнені, що не маєте жодних образливих цінностей? Немає порожніх рядків? Немає пробільних чи кінцевих пробілів? Різниці випадків? Наголошені символи?
Асаф

1
@Zaid Я думаю, що у вашій таблиці є значення, які відсутні у вашому оновленому визначенні ENUM. Ваше нове визначення дозволяє лише Швеція та Малайзія. У вашій таблиці є США, Індія, Німеччина ... Жодне з цих значень не буде дозволено у вашому новому ENUM. Якщо ви намагаєтеся зробити це - додати Швецію та Малайзію, зберігаючи вихідні члени ENUM, вам потрібно буде перерахувати всі початкові значення ENUM плюс 2 нові у вашій заяві ALTER.
Асаф

2
@Zaid Безкоштовно Якщо ви використовуєте таблицю країн із іноземним ключем замість ENUM, як я запропонував на початку, ви зможете просто додати рядки для нових країн. BTW: Якщо ви вважаєте мої пропозиції корисними, будь ласка, позначте мою відповідь правильною :)
Асаф

3
-1 Через відсутність ясності щодо того, яке саме тут є рішення. Занадто багато розмови і багато "спробуйте це, ну добре спробуйте це замість цього". Первісна відповідь навіть не відповідає дійсному питанню ОП - це не пізніше, коли ви зрозумієте, в чому проблема, і тоді ви переходите до простих зразків коду, які насправді нічого не означають для того, хто знайде це питання / відповідь пізніше. Контекст ваших редагувань є / був часовим і більше не очевидним.
Джим Рубенштейн

73

Обговорення я мав з Асафа може бути нечітким , щоб слідувати , як ми пішли вперед і назад зовсім небагато.

Я думав, що я можу прояснити підсумок нашого дискурсу для інших, хто може зіткнутися з подібними ситуаціями в майбутньому, щоб отримати вигоду з:

ENUM-типи стовпчиків дуже важко маніпулювати. Я хотів додати дві країни (Малайзія та Швеція) до існуючого набору країн у своєму ENUM.

Здається, що MySQL 5.1 (що я і працюю) може оновити ENUM лише шляхом переосмислення наявного набору, крім того, що я хочу:

Це не спрацювало:

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

Причина полягала в тому , що заява MySQL було замінити існуючий ENUM з іншого , що містять записи 'Malaysia'і 'Sweden'тільки. MySQL кинув помилку , тому що carmakeтаблиця вже була цінності , як 'England'і 'USA'які не є частиною нового ENUMвизначення «s.

Дивно, але наступне не працювало:

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

Виявляється, навіть порядок елементів існуючих ENUMпотрібно зберігати, додаючи до нього нових членів. Отже, якщо моє існуюче ENUMвиглядає приблизно так ENUM('England','USA'), то моє нове ENUMмає бути визначене як « ENUM('England','USA','Sweden','Malaysia')ні» ENUM('USA','England','Sweden','Malaysia'). Ця проблема виявляється лише тоді, коли в існуючій таблиці є записи, які використовують 'USA'або 'England'значать.

НИЖНЯ ЛІНІЯ:

Використовуйте ENUMs лише тоді, коли ви не очікуєте, що ваш набір членів зміниться, коли вони визначені. Інакше таблиці пошуку набагато простіше оновлювати та змінювати.


Я б задумався про більш сильний підсумок ... "використовуйте ENUM лише тоді, коли ви на 100% мертві, певний позитив, що значення ніколи не зміниться". Якщо таблиця зростає великою, буде біль, якщо вам коли-небудь доведеться змінити ці значення.
DougW

6
Я не впевнений, що згоден з цим підсумком. Повірте мені, що мені зовсім не подобаються ENUM, але я не бачу небезпеки в додаванні до можливого ENUM. ENUM - це, по суті, відображення 0 -> Варіант 1, 1-> Варіант 2 і т.д. Додавання цього не повинно викликати проблем.
JoshStrange

2
@JoshStrange Це не стільки небезпека, це може бути величезна незручність, коли важливий порядок роботи вашого ENUM (наприклад, коли він використовується для замовлення).
1in9ui5t

1
Я думаю, що важливо також сказати в нижньому рядку, що це дійсно лише для застарілих версій MySQL, тому що, наскільки я розумію, з новими проблемами немає.
Niccolò

Ця відповідь більше не актуальна, таку, яку нижче, слід позначати як прийняту.
ofirski

16

У версії сервера MYSQL: 5.0.27 я спробував це, і він добре працював, щоб я перевірив вашу версію

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

1
Не впевнений, чому цього більше не підтримують. Це просто, і це працює для мене.
родовий

1

FYI: Корисний інструмент моделювання - phpMyAdmin з Wampserver 3.0.6 - Попередній перегляд SQL: Я використовую 'Preview SQL', щоб побачити код SQL, який буде створений перед збереженням стовпця зі зміною на ENUM. Попередній перегляд SQL

Вище бачите, що я ввійшов до "END", "Toyota" в ENUM, але я отримую синтаксис ENUM (0), який генерує синтаксичну помилку запиту 1064 #

Потім я копіюю та вставляю та змінюю SQL і запускаю його через SQL з позитивним результатом.

SQL змінено

Це швидке виправлення, яке я часто використовую, а також може бути використане для існуючих значень ENUM, які потрібно змінити. Думав, що це може бути корисним.


1

Ось ще один спосіб ...

Він додає "інші" до переліку визначення стовпця "rtipo" таблиці "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

Це можливо, якщо ви вірите. Хе-хе. спробуйте цей код.

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)");
  }

Перш ніж додати нове значення

Після додавання нової вартості


11
Я не бачу, як це приносить щось нове на стіл. Питання також з точки зору MySQL. Ваша відповідь містить випадковий PHP, який абсолютно не має значення, і ви не намагаєтесь пояснити будь-яке. Марний ресурс інформації
Джонатан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.