2009-10-01 15 views
104

Il manuale di riferimento MySQL non fornisce un esempio di cancellazione su come eseguire questa operazione.Come posso aggiungere altri membri alla mia colonna di tipo ENUM in MySQL?

Ho una colonna di nomi di paese di tipo ENUM a cui ho bisogno di aggiungere altri paesi. Qual è la sintassi corretta di MySQL per raggiungere questo obiettivo?

Ecco il mio tentativo:

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

L'errore che ottengo è: ERROR 1265 (01000): Data truncated for column 'country' at row 1.

La colonna country è la colonna ENUM-tipo nel già comunicato.

SHOW CREATE TABLE USCITA:

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) 

Selezionare Paese DISTINTO DA carmake USCITA:

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

risposta

63

Il discussion che ho avuto con Asaf può essere poco chiaro da seguire come siamo andati avanti e indietro un po '.

ho pensato che avrei potuto chiarire il risultato del nostro discorso per altri che potrebbero affrontare situazioni simili in futuro a beneficiare di:

ENUM colonne -tipo sono bestie molto difficile da manipolare. Volevo aggiungere due paesi (Malaysia & Svezia) al set esistente di paesi nel mio ENUM.

Sembra che MySQL 5.1 (che è quello che sono in esecuzione) può aggiornare solo l'ENUM ridefinendo l'insieme esistente in aggiunta a quello che voglio:

questo non ha funzionato:

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

Il motivo era che la dichiarazione MySQL sostituiva l'ENUM esistente con un'altra contenente le voci 'Malaysia' e 'Sweden'. MySQL ha generato un errore perché la tabella carmake aveva già valori come 'England' e 'USA' che non facevano parte della nuova definizione di ENUM.

Sorprendentemente, quanto segue non ha funzionato neanche:

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

Si scopre che anche l'ordine degli elementi delle esistenti ENUM deve essere preservato, mentre l'aggiunta di nuovi membri ad esso. Quindi, se il mio attuale ENUM è simile a ENUM('England','USA'), il mio nuovo ENUM deve essere definito come ENUM('England','USA','Sweden','Malaysia') e non ENUM('USA','England','Sweden','Malaysia'). Questo problema si manifesta solo quando nella tabella esistente sono presenti record che utilizzano valori 'USA' o 'England'.

BOTTOM LINE:

utilizzare solo ENUM s quando non si aspetta il set di membri per cambiare una volta definito. Altrimenti, le tabelle di ricerca sono molto più facili da aggiornare e modificare.

+0

Avrei azzardato una linea di fondo più forte ... "usa ENUM solo quando sei al 100% morto, certo che i valori non cambieranno mai". Se un tavolo diventa più grande, sarà un problema se dovessi cambiare quei valori. – DougW

+5

Non sono sicuro di essere d'accordo con questa linea di fondo. Fidati di me non mi piace affatto ENUM ma non vedo il pericolo nell'aggiungere al possibile ENUM. ENUM è, al suo centro, una mappatura di 0 -> Opzione 1, 1-> Opzione 2, ecc. L'aggiunta a ciò non dovrebbe causare un problema. – JoshStrange

+2

@JoshStrange Non è tanto un pericolo, può essere un enorme inconveniente quando l'ordine del tuo ENUM è importante (ad esempio, se usato per l'ordine). – 1in9ui5t

84

Il codice funziona per me. Ecco il mio test case:

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) 

Che errore stai vedendo?

FWIW questo dovrebbe funzionare anche:

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

vorrei davvero raccomandare una tabella di paese piuttosto che di colonna enum. Potresti avere centinaia di paesi che farebbero un enum piuttosto grande e imbarazzante.

EDIT: Ora che posso vedere il tuo messaggio di errore:

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

ho il sospetto di avere alcuni valori nella colonna Paese che non compaiono nel vostro ENUM. Qual è l'output del seguente comando?

SELECT DISTINCT country FROM carmake;

UN ALTRO MODIFICA: qual è l'output del seguente comando?

SHOW VARIABLES LIKE 'sql_mode';

E 'STRICT_TRANS_TABLES o STRICT_ALL_TABLES? Ciò potrebbe portare a un errore, piuttosto che al solito avvertimento che MySQL ti avrebbe dato in questa situazione.

ANCORA UN ALTRO MODIFICO: Ok, ora vedo che nella tabella non sono presenti valori che non si trovano nel nuovo ENUM. La nuova definizione ENUM consente solo 'Sweden' e 'Malaysia'. Il tavolo ha 'USA', 'India' e molti altri.

ultima modifica (forse): Penso che si sta cercando di fare questo:

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

C'è più di una colonna nel mio 'tavolo carmake'. Potrebbe avere qualcosa a che fare con questo? – Zaid

+0

Improbabile, ma pubblicare l'output di questo comando "SHOW CREATE TABLE carmake" e lo guarderò. – Asaph

+0

@Zaid Vedo che hai aggiunto il messaggio di errore "L'errore che ottengo è: ERRORE 1265 (01000): dati troncati per la colonna" Paese "nella riga 1.". Penso che il problema è che hai già dei valori nella colonna del paese che non sono elencati nell'enumerazione. – Asaph

-7

È possibile se credi. Hehe. prova questo codice

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

Non vedo come questo porti qualcosa di nuovo al tavolo. La domanda è puramente da un punto di vista MySQL. La tua risposta incorpora PHP casuali che è del tutto irrilevante e non fai alcun tentativo di spiegare nulla di ciò.Risorsa inutile di informazioni – 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

una risposta chiara e veloce utilizzabile. – Andrew

0

FYI: Un utile strumento di simulazione - phpMyAdmin con Wampserver 3.0.6 - SQL in anteprima: Io uso 'Preview di SQL' per vedere il codice SQL che avrebbe essere generato prima di salvare la colonna con la modifica a ENUM. Preview SQL

Sopra si vede che ho inserito 'Ford', 'Toyota' nella ENUM, ma io sono sempre la sintassi ENUM (0), che sta generando errore di sintassi Query error 1064#

ho quindi copiare e incollare e modificare il codice SQL ed eseguirlo tramite SQL con un risultato positivo.

SQL changed

Questa è una quickfix che uso spesso e può essere utilizzato anche su valori ENUM che hanno bisogno di essere modificato esistente. Ho pensato che questo potrebbe essere utile.

0

Nella versione del server MySQL: 5.0.27 Ho provato questo e ha funzionato bene per me il check-nella versione

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