Puis-je renommer les valeurs d'une colonne MySQL ENUM en une seule requête?

12

Supposons que j'ai une table de base de données avec un ENUM('value_one','value_two'). Je veux changer cela en un ENUM('First value','Second value'). Je fais actuellement cela comme suit:

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');

Existe-t-il un moyen plus efficace de le faire, par exemple un moyen d'accomplir cela avec une seule ALTER TABLE déclaration?

Josh
la source

Réponses:

10

La technique de follolwing que je vais vous montrer nécessitera des tripes d'acier.

Compte tenu des critères suivants

  • datadir est /var/lib/mysql
  • la table est mydb.mytb
  • la colonne enum appelée est appelée enum_col
  • le moteur est MyISAM

Voici une fissure qui défie la mort:

  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. Dans une session OS / SSH distincte, échangez les fichiers .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;

C'est ça !!!

CAVEAT: JE NE PEUX PAS PRENDRE DE CRÉDIT POUR CELA!

Cette technique provient de «MySQL hautes performances: optimisation, sauvegardes, réplication, etc.», pages 146-148 sous le sous-titre Accélérer ALTER TABLE . Page 147 Le paragraphe 1 dit:

La technique que nous sommes sur le point de démontrer n'est pas prise en charge, n'est pas documentée et peut ne pas fonctionner. Utilisez à vos risques et périls. Nous vous conseillons de sauvegarder vos données en premier!

Essaie ! (S'il vous plaît laissez-nous savoir comment cela s'est avéré)

MISE À JOUR 2011-10-05 17:49 EDT

Si la table est MyISAM et que vous disposez de suffisamment d'espace de production et d'une fenêtre d'indisponibilité directe, essayez ceci:

  1. service mysql restart --skip-networking

  2. Dans une session OS / SSH distincte, faites une copie du tableau

    • 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.TABLESdétectera automatiquement la présence de la nouvelle table appelée mydb.mytbplay.

  1. Exécutez l'algorithme des entrailles d'acier sur mydb.mytbplay

  2. Vous testez l'intégrité de mydb.mytbplay

Si vous êtes satisfait

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

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

  3. service mysql restart

Essaie!

RolandoMySQLDBA
la source
+1 pour une réponse ingénieuse! Cependant, je ne vais pas essayer ceci et vous faire savoir comment cela s'est passé car la question fait référence à un script de mise à niveau pour toutes les bases de données de production en direct de mes clients ;-) Je peux cependant essayer ceci dans un environnement de développement juste pour s'amuser. Mais avec cet avertissement, je ne ferais jamais ça en production!
Josh
3

Une solution simple serait:

1- ajouter une nouvelle colonne:

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

2- Copiez la valeur de la colonne dans enum2 avec remplacements:

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

3- colonne goutte column, changement de nom enumà column.

REMARQUE : cette question remonte au 2011-10-05, ma solution est valide pour MYSQL 4.1 et plus récent (AFAIK)

Abdelkader Mh
la source
Bien que cela semble être une bonne solution (et pas aussi angoissante que la réponse acceptée!), Il convient de noter que l'étape 3 nécessite au moins une ALTER TABLEdéclaration, et l'OP recherchait quelque chose qui n'en exigeait qu'une. Encore une fois, cela dit, cela semble être une solution solide parfaitement standard.
RDFozz