125 votes

ALTER TABLE ADD COLUMN IF NOT EXISTS dans SQLite

Nous avons récemment eu besoin d'ajouter des colonnes à quelques-unes de nos tables de base de données SQLite existantes. Cela peut être fait avec ALTER TABLE ADD COLUMN . Bien entendu, si la table a déjà été modifiée, nous voulons la laisser telle quelle. Malheureusement, SQLite ne prend pas en charge la fonction IF NOT EXISTS clause sur ALTER TABLE .

Notre solution actuelle consiste à exécuter l'instruction ALTER TABLE et à ignorer les erreurs de type "nom de colonne en double", de la manière suivante cet exemple Python (mais en C++).

Cependant, notre approche habituelle de la mise en place de schémas de base de données consiste à disposer d'un script .sql contenant les éléments suivants CREATE TABLE IF NOT EXISTS y CREATE INDEX IF NOT EXISTS qui peuvent être exécutées à l'aide de sqlite3_exec ou le sqlite3 outil de ligne de commande. Nous ne pouvons pas mettre ALTER TABLE dans ces fichiers script car si cette instruction échoue, tout ce qui suit ne sera pas exécuté.

Je souhaite que les définitions des tables soient regroupées en un seul endroit et ne soient pas réparties entre les fichiers .sql et .cpp. Existe-t-il un moyen d'écrire une solution de contournement pour ALTER TABLE ADD COLUMN IF NOT EXISTS en SQLite pur ?

14voto

Krunal Shah Points 215

Il y a une méthode de PRAGMA qui est table_info(nom_de_la_table), elle renvoie toutes les informations de la table.

Voici comment l'utiliser pour vérifier si une colonne existe ou non,

    public boolean isColumnExists (String table, String column) {
         boolean isExists = false
         Cursor cursor;
         try {           
            cursor = db.rawQuery("PRAGMA table_info("+ table +")", null);
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    String name = cursor.getString(cursor.getColumnIndex("name"));
                    if (column.equalsIgnoreCase(name)) {
                        isExists = true;
                        break;
                    }
                }
            }

         } finally {
            if (cursor != null && !cursor.isClose()) 
               cursor.close();
         }
         return isExists;
    }

Vous pouvez également utiliser cette requête sans utiliser de boucle,

cursor = db.rawQuery("PRAGMA table_info("+ table +") where name = " + column, null);

0voto

stevesweets Points 6

Si vous avez ce problème avec flex/adobe air et que vous vous retrouvez d'abord ici, j'ai trouvé une solution, et je l'ai postée sur une question connexe : ADD COLUMN to sqlite db IF NOT EXISTS - flex/air sqlite ?

Mon commentaire ici : https://stackoverflow.com/a/24928437/2678219

0voto

user1069671 Points 51

Vous pouvez également utiliser l'instruction TSQL CASE-WHEN en combinaison avec pragma_table_info pour savoir si une colonne existe :

select case(CNT) 
    WHEN 0 then printf('not found')
    WHEN 1 then printf('found')
    END
FROM (SELECT COUNT(*) AS CNT FROM pragma_table_info('myTableName') WHERE name='columnToCheck')

0voto

Jaro B Points 21
select * from sqlite_master where type = 'table' and tbl_name = 'TableName' and sql like '%ColumnName%'

Logique : la colonne sql dans sqlite_master contient la définition de la table, donc elle contient certainement une chaîne avec le nom de la colonne.

Comme vous recherchez une sous-chaîne, cette méthode présente des limites évidentes. Je suggérerais donc d'utiliser une sous-chaîne encore plus restrictive dans ColumnName, par exemple quelque chose comme ceci (sous réserve de tests car le caractère '`' n'est pas toujours présent) :

select * from sqlite_master where type = 'table' and tbl_name = 'MyTable' and sql like '%`MyColumn` TEXT%'

-1voto

Kevin B Burns Points 793

J'ai pris la réponse ci-dessus en C#/.Net, et je l'ai réécrite pour Qt/C++, sans trop de changement, mais je voulais la laisser ici pour ceux qui, à l'avenir, chercheraient une réponse en C++.

    bool MainWindow::isColumnExisting(QString &table, QString &columnName){

    QSqlQuery q;

    try {
        if(q.exec("PRAGMA table_info("+ table +")"))
            while (q.next()) {
                QString name = q.value("name").toString();     
                if (columnName.toLower() == name.toLower())
                    return true;
            }

    } catch(exception){
        return false;
    }
    return false;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X