web-dev-qa-db-fra.com

vérifie si la colonne existe avant ALTER TABLE - mysql

Existe-t-il un moyen de vérifier si une colonne existe dans une base de données mySQL avant (ou sous) l'exécution de l'instruction ALTER TABLE ADD coumn_name? Tri d'une chose IF column DOES NOT EXIST ALTER TABLE.

J'ai essayé ALTER IGNORE TABLE my_table ADD my_column mais cela jette toujours l'erreur si la colonne que j'ajoute existe déjà.

EDIT: le cas d’utilisation consiste à mettre à jour une table dans une application Web déjà installée - alors, pour rester simple, je veux être sûr que les colonnes dont j’ai besoin existent, et si ce n’est pas le cas, ajoutez-les en utilisant ALTER TABLE

18
julio

Etant donné que les instructions de contrôle mysql (par exemple, "IF") ne fonctionnent que dans les procédures stockées, une instruction temporaire peut être créée et exécutée:

DROP PROCEDURE IF EXISTS add_version_to_actor;

DELIMITER $$

CREATE DEFINER=CURRENT_USER PROCEDURE add_version_to_actor ( ) 
BEGIN
DECLARE colName TEXT;
SELECT column_name INTO colName
FROM information_schema.columns 
WHERE table_schema = 'connjur'
    AND table_name = 'actor'
AND column_name = 'version';

IF colName is null THEN 
    ALTER TABLE  actor ADD  version TINYINT NOT NULL DEFAULT  '1' COMMENT  'code version of actor when stored';
END IF; 
END$$

DELIMITER ;

CALL add_version_to_actor;

DROP PROCEDURE add_version_to_actor;
9
gerardw

Pensez-vous pouvoir essayer ceci ?:

SELECT IFNULL(column_name, '') INTO @colName
FROM information_schema.columns 
WHERE table_name = 'my_table'
AND column_name = 'my_column';

IF @colName = '' THEN 
    -- ALTER COMMAND GOES HERE --
END IF;

Ce n'est pas une ligne, mais pouvez-vous au moins voir si cela fonctionnera pour vous? Au moins en attendant une meilleure solution ..

8
Nonym

Fonctions et procédures utilitaires

Tout d'abord, j'ai un ensemble de fonctions utilitaires et de procédures que j'utilise pour effectuer des opérations telles que la suppression de clés étrangères, de clés normales et de colonnes. Je les laisse simplement dans la base de données pour pouvoir les utiliser au besoin.

Les voici.

delimiter $$

create function column_exists(ptable text, pcolumn text)
  returns bool
  reads sql data
begin
  declare result bool;
  select
    count(*)
  into
    result
  from
    information_schema.columns
  where
    `table_schema` = 'my_database' and
    `table_name` = ptable and
    `column_name` = pcolumn;
  return result;
end $$

create function constraint_exists(ptable text, pconstraint text)
  returns bool
  reads sql data
begin
  declare result bool;
  select
    count(*)
  into
    result
  from
    information_schema.table_constraints
  where
    `constraint_schema` = 'my_database' and
    `table_schema` = 'my_database' and
    `table_name` = ptable and
    `constraint_name` = pconstraint;
  return result;
end $$

create procedure drop_fk_if_exists(ptable text, pconstraint text)
begin
  if constraint_exists(ptable, pconstraint) then
    set @stat = concat('alter table ', ptable, ' drop foreign key ', pconstraint);
    prepare pstat from @stat;
    execute pstat;
  end if;
end $$

create procedure drop_key_if_exists(ptable text, pconstraint text)
begin
  if constraint_exists(ptable, pconstraint) then
    set @stat = concat('alter table ', ptable, ' drop key ', pconstraint);
    prepare pstat from @stat;
    execute pstat;
  end if;
end $$

create procedure drop_column_if_exists(ptable text, pcolumn text)
begin
  if column_exists(ptable, pcolumn) then
    set @stat = concat('alter table ', ptable, ' drop column ', pcolumn);
    prepare pstat from @stat;
    execute pstat;
  end if;
end $$

delimiter ;

Suppression de contraintes et de colonnes à l'aide des utilitaires ci-dessus

Avec ceux en place, il est assez facile de les utiliser pour vérifier l'existence des colonnes et des contraintes:

-- Drop service.component_id
call drop_fk_if_exists('service', 'fk_service_1');
call drop_key_if_exists('service', 'component_id');
call drop_column_if_exists('service', 'component_id');

-- Drop commit.component_id
call drop_fk_if_exists('commit', 'commit_ibfk_1');
call drop_key_if_exists('commit', 'commit_idx1');
call drop_column_if_exists('commit', 'component_id');

-- Drop component.application_id
call drop_fk_if_exists('component', 'fk_component_1');
call drop_key_if_exists('component', 'application_id');
call drop_column_if_exists('component', 'application_id');
6
Willie Wheeler

Faites une phrase de comptage avec l'exemple ci-dessous de John Watson. 

 SELECT count(*) FROM information_schema.COLUMNS
     WHERE COLUMN_NAME = '...'
     and TABLE_NAME = '...'
     and TABLE_SCHEMA = '...'

Enregistrez ce résultat dans un entier, puis indiquez comme condition d'appliquer la phrase ADD COLUMN.

2
Duvan Barros

Bien que ce soit un vieux post, mais je suis toujours heureux de partager ma solution à ce problème. Si la colonne n'existe pas, une exception se produirait définitivement et je crée alors la colonne dans la table. 

Je viens d'utiliser le code ci-dessous:

 try
   {
         DATABASE_QUERY="SELECT gender from USER;";
         db.rawQuery(DATABASE_QUERY, null);
   }
   catch (Exception e)
   {
    e.printStackTrace();

        DATABASE_UPGRADE="alter table USER ADD COLUMN gender VARCHAR(10) DEFAULT 0;";
                db.execSQL(DATABASE_UPGRADE);
   } 
1
Wahib Ul Haq
DELIMITER $$

DROP PROCEDURE IF EXISTS `addcol` $$
CREATE DEFINER=`admin`@`localhost` PROCEDURE `addcol`(tbn varchar(45), cn varchar(45), ct varchar(45))
BEGIN
#tbn: table name, cn: column name, ct: column type
DECLARE CONTINUE HANDLER FOR 1060 BEGIN END;
set cn = REPLACE(cn, ' ','_');
set @a = '';
set @a = CONCAT("ALTER TABLE `", tbn ,"` ADD column `", cn ,"` ", ct);
PREPARE stmt FROM @a;
EXECUTE stmt;

END $$

DELIMITER ;
0
Richards RIc

Vous pouvez créer une procédure avec un gestionnaire CONTINUE au cas où la colonne existe (veuillez noter que ce code ne fonctionne pas dans PHPMyAdmin):

DROP PROCEDURE IF EXISTS foo;
CREATE PROCEDURE foo() BEGIN
    DECLARE CONTINUE HANDLER FOR 1060 BEGIN END;
    ALTER TABLE `tableName` ADD `columnName` int(10) NULL AFTER `otherColumn`;
END;
CALL foo();
DROP PROCEDURE foo;

Ce code ne doit générer aucune erreur si la colonne existe déjà. Il ne fera que rien et continuera à exécuter le reste du code SQL.

0
OMA