Question

Comment ALTER peut-il être utilisé pour supprimer une colonne dans une table MySQL si cette colonne existe?

Je sais que je peux utiliser ALTER TABLE ma_table DROP COLUMN ma_colonne , mais cela jettera une erreur si ma_colonne n'existe pas. Existe-t-il une autre syntaxe pour supprimer la colonne de manière conditionnelle?

J'utilise MySQL version 4.0.18.

Était-ce utile?

La solution

Pour MySQL, il n'y en a aucun: demande de fonctionnalité MySQL .

Permettre cela est sans doute une très mauvaise idée, en tout cas: IF EXISTS indique que vous exécutez des opérations destructives sur une base de données avec une structure inconnue (pour vous). Il peut y avoir des situations où cela est acceptable pour un travail local rapide et délicat, mais si vous êtes tenté d'exécuter une telle déclaration contre des données de production (dans une migration, etc.), vous jouez avec le feu.

Mais si vous insistez, il n'est pas difficile de vérifier l'existence au préalable dans le client ou de détecter l'erreur.

MariaDB prend également en charge les éléments suivants à partir de 10.0.2:

  

DROP [COLUMN] [IF EXISTS] nom_colonne

i. e.

  

ALTER TABLE my_table DROP IF EXISTS my_column;

Mais c’est sans doute une mauvaise idée de s’appuyer sur une fonctionnalité non standard supportée par une seule des nombreuses fourchettes de MySQL.

Autres conseils

Il n’existe pas de support de niveau de langue pour cela dans MySQL. Voici un moyen de contourner les méta-données MySQL information_schema dans la version 5.0+, mais cela ne résoudra pas votre problème dans la version 4.0.18.

drop procedure if exists schema_change;

delimiter ';;'
create procedure schema_change() begin

    /* delete columns if they exist */
    if exists (select * from information_schema.columns where table_schema = schema() and table_name = 'table1' and column_name = 'column1') then
        alter table table1 drop column `column1`;
    end if;
    if exists (select * from information_schema.columns where table_schema = schema() and table_name = 'table1' and column_name = 'column2') then
        alter table table1 drop column `column2`;
    end if;

    /* add columns */
    alter table table1 add column `column1` varchar(255) NULL;
    alter table table1 add column `column2` varchar(255) NULL;

end;;

delimiter ';'
call schema_change();

drop procedure if exists schema_change;

J'ai écrit des informations plus détaillées dans un article de blog .

Je sais que c'est un ancien fil de discussion, mais il existe un moyen simple de gérer cette exigence sans utiliser de procédures stockées. Cela peut aider quelqu'un.

set @exist_Check := (
    select count(*) from information_schema.columns 
    where TABLE_NAME='YOUR_TABLE' 
    and COLUMN_NAME='YOUR_COLUMN' 
    and TABLE_SCHEMA=database()
) ;
set @sqlstmt := if(@exist_Check>0,'alter table YOUR_TABLE drop column YOUR_COLUMN', 'select ''''') ;
prepare stmt from @sqlstmt ;
execute stmt ;

J'espère que cela aide quelqu'un, comme cela m'a été fait (après beaucoup d'essais et d'erreurs).

Je viens de créer une procédure réutilisable qui peut aider à rendre DROP COLUMN idempotent:

-- column_exists:

DROP FUNCTION IF EXISTS column_exists;

DELIMITER $
CREATE FUNCTION column_exists(
  tname VARCHAR(64),
  cname VARCHAR(64)
)
  RETURNS BOOLEAN
  READS SQL DATA
  BEGIN
    RETURN 0 < (SELECT COUNT(*)
                FROM `INFORMATION_SCHEMA`.`COLUMNS`
                WHERE `TABLE_SCHEMA` = SCHEMA()
                      AND `TABLE_NAME` = tname
                      AND `COLUMN_NAME` = cname);
  END $
DELIMITER ;

-- drop_column_if_exists:

DROP PROCEDURE IF EXISTS drop_column_if_exists;

DELIMITER $
CREATE PROCEDURE drop_column_if_exists(
  tname VARCHAR(64),
  cname VARCHAR(64)
)
  BEGIN
    IF column_exists(tname, cname)
    THEN
      SET @drop_column_if_exists = CONCAT('ALTER TABLE `', tname, '` DROP COLUMN `', cname, '`');
      PREPARE drop_query FROM @drop_column_if_exists;
      EXECUTE drop_query;
    END IF;
  END $
DELIMITER ;

Utilisation:

CALL drop_column_if_exists('my_table', 'my_column');

Exemple:

SELECT column_exists('my_table', 'my_column');       -- 1
CALL drop_column_if_exists('my_table', 'my_column'); -- success
SELECT column_exists('my_table', 'my_column');       -- 0
CALL drop_column_if_exists('my_table', 'my_column'); -- success
SELECT column_exists('my_table', 'my_column');       -- 0

La réponse de Chase Seibert fonctionne, mais je voudrais ajouter que si vous avez plusieurs schémas, vous voulez modifier le SELECT de la manière suivante:

select * from information_schema.columns where table_schema in (select schema()) and table_name=...

Je réalise que ce fil est assez ancien maintenant, mais je rencontrais le même problème. C’était ma solution de base avec MySQL Workbench, mais cela a bien fonctionné ...

  1. récupérez un nouvel éditeur SQL et exécutez SHOW TABLES pour obtenir une liste de vos tables
  2. sélectionnez toutes les lignes et choisissez l'option Copier dans le presse-papier (sans guillemets) dans le menu contextuel
  3. .
  4. collez la liste des noms dans un autre onglet d'édition
  5. écrivez votre requête, c'est-à-dire ALTER TABLE x DROP a ;
  6. faites un peu de copier-coller pour vous retrouver avec une requête séparée pour chaque table
  7. Indiquez si le plan de travail doit s'arrêter en cas d'erreur
  8. Appuyez sur Exécuter et parcourez le journal de sortie

les tables qui avaient la table ont maintenant pas toutes les tables qui n'auraient pas montré d'erreur dans les journaux

alors vous pouvez trouver / remplacer 'drop a ', changez le en 'ADD COLUMN b INT NULL' etc. et relancez le tout ....

un peu maladroit, mais vous obtenez enfin le résultat final, vous pouvez contrôler / surveiller tout le processus et vous rappeler de sauvegarder vos scripts SQL au cas où vous en auriez besoin à nouveau.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top