2009-10-01 7 views
104

W podręczniku referencyjnym MySQL nie podano przykładowego sposobu wykonania tej czynności.Jak dodać więcej członków do mojej kolumny typu ENUM w MySQL?

Mam kolumnę nazwy krajów typu ENUM, która jest potrzebna do dodania kolejnych krajów. Jaka jest poprawna składnia MySQL, aby to osiągnąć?

Oto moja próba:

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

Błąd pojawia się: ERROR 1265 (01000): Data truncated for column 'country' at row 1.

Kolumna country jest kolumna typu ENUM w wyżej oświadczeniu.

SHOW CREATE TABLE wyjściowa:

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 kraj z carmake wyjściowa:

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

Odpowiedz

63

discussion miałem z Asafa mogą być niejasne podążać jak poszliśmy tam i z powrotem całkiem sporo.

Myślałem, że mogę wyjaśnić Konsekwencją naszego dyskursu dla innych, którzy mogą napotkać podobne sytuacje w przyszłości korzystać z:

ENUM kolumny typu a są bardzo trudne do manipulowania bestie. Chciałem dodać dwa kraje (Malezja & Szwecja) do istniejącego zestawu krajów w moim ENUM.

Wydaje się, że MySQL 5.1 (czego używam) można tylko zaktualizować ENUM poprzez przedefiniowanie zestawu istniejącego oprócz tego, co chcę:

To nie działa:

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

Powodem było to, że instrukcja MySQL zastępowała istniejącą ENUM inną zawierającą tylko pozycje 'Malaysia' i 'Sweden'. MySQL zwrócił błąd, ponieważ tabela ma już wartości takie jak 'England' i 'USA', które nie były częścią nowej definicji ENUM.

Zaskakująco dodaje nie działa albo:

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

Okazuje się, że nawet kolejność elementów istniejących ENUM powinno być zachowane podczas dodawania nowych członków do niego. Więc jeśli mój istniejący ENUM wygląda jak ENUM('England','USA'), mój nowy ENUM musi być zdefiniowany jako ENUM('England','USA','Sweden','Malaysia'), a nie ENUM('USA','England','Sweden','Malaysia'). Ten problem pojawia się tylko wtedy, gdy istnieją zapisy w istniejącej tabeli, które używają wartości 'USA' lub 'England'.

Konkluzja:

używać tylko ENUM s, jeśli nie oczekiwać zestaw członków zmienić raz zdefiniowane. W przeciwnym razie tabele odnośników można znacznie łatwiej aktualizować i modyfikować.

+0

Zaryzykowałbym mocniejszą linię podstawową ... "używaj tylko ENUM, gdy jesteś w 100% martwy, pewny, że wartości nigdy się nie zmienią". Jeśli stół się powiększy, będzie to bolało, jeśli będziesz musiał zmienić te wartości. – DougW

+5

Nie jestem pewien, czy zgadzam się z tą podstawową linią. Zaufaj mi, że w ogóle nie lubię ENUM, ale nie widzę niebezpieczeństwa w DODANIU do możliwej ENUM. ENUM jest, w jego rdzeniu, mapowaniem 0 -> Opcja 1, 1-> Opcja 2, itp. Dodanie do tego nie powinno powodować problemu. – JoshStrange

+2

@JoshStrange To nie jest takie niebezpieczeństwo, może być ogromną niedogodnością, gdy kolejność ENUM jest ważna (na przykład, gdy jest używana do zamawiania). – 1in9ui5t

84

Twój kod działa dla mnie. Oto mój test:

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) 

Jakiego błędu widzisz?

FWIW to będzie działać również:

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

bym rzeczywiście polecić stół kraj zamiast kolumny enum. Możecie mieć setki krajów, które pozwolą na dość duże i niezręczne wyliczenie.

EDIT: Teraz, gdy widzę wiadomość o błędzie:

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

Podejrzewam masz jakieś wartości w kolumnie kraju, które nie pojawiają się w ENUM. Jaki jest wynik działania następującego polecenia?

SELECT DISTINCT country FROM carmake;

KOLEJNA EDYCJA: Jakie jest wyjście z następującego polecenia?

SHOW VARIABLES LIKE 'sql_mode';

Czy STRICT_TRANS_TABLES lub STRICT_ALL_TABLES? To może doprowadzić do błędu, a nie zwykłego ostrzeżenia, jakie MySQL dałoby ci w tej sytuacji.

JEDNA KOLEJNA EDYCJA: Ok, teraz widzę, że zdecydowanie masz wartości w tabeli, które nie są w nowym ENUM. Nowa definicja ENUM umożliwia tylko 'Sweden' i 'Malaysia'. Tabela ma 'USA', 'India' i kilka innych.

ostatniej edycji (być może): Myślę, że próbujesz to zrobić:

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

Jest więcej niż jedna kolumna w moim 'carmake' tabeli. Czy to może mieć z tym coś wspólnego? – Zaid

+0

Jest mało prawdopodobne, ale opublikuj dane wyjściowe tego polecenia "POKAŻ CREATE TABLE carmake" i przyjrzę się temu. – Asaph

+0

@ Zaid Widzę, że dodano komunikat o błędzie "Wystąpił błąd: ERROR 1265 (01000): Dane skrócone dla kolumny" kraj "w wierszu 1.". Myślę, że problem polega na tym, że masz wartości już w kolumnie kraju, które nie są wymienione w wyliczeniu. – Asaph

-7

Jest to możliwe, jeśli wierzysz. Hehe. spróbuj tego kodu.

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

Before adding new value

After adding new value

+6

Nie widzę, jak to przynosi coś nowego do stołu. Pytanie jest również z punktu widzenia MySQL. Twoja odpowiedź zawiera losowy PHP, który jest zupełnie nieistotny i nie próbujesz wyjaśnić żadnego z nich.Bezużyteczny zasób informacji – Jonathan

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

jasna i szybka użyteczna odpowiedź dzięki. – Andrew

0

FYI: Użyteczne narzędzie do symulacji - phpMyAdmin z -WampSerwer 3.0.6 - Podgląd SQL: Używam 'Podgląd SQL', aby zobaczyć kod SQL, które być wygenerowane przed zapisaniem kolumny ze zmianą na ENUM. Preview SQL

Powyżej widać, że weszły „Ford”, „Toyota” w ENUM, ale jestem coraz składnia ENUM (0), który generuje błąd składni Query error 1064#

I skopiuj i wklej i zmieniać SQL i uruchomić go przez SQL z wynikiem dodatnim.

SQL changed

To quickfix że używam często i może być również stosowany na istniejących wartości ENUM, które muszą zostać zmienione. Myślałem, że to może być przydatne.

0

W wersji serwera MySQL: 5.0.27 Próbowałem to i to działało w porządku dla mnie sprawdzić w swojej wersji

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