web-dev-qa-db-fra.com

Supprimer la colonne de la table SQLite

J'ai un problème: je dois supprimer une colonne de ma base de données SQLite. J'ai écrit cette requête

alter table table_name drop column column_name 

mais ça ne marche pas. Aidez-moi, s'il vous plaît.

92
sandy

De: http://www.sqlite.org/faq.html :

(11) Comment ajouter ou supprimer des colonnes d'une table existante dans SQLite.

SQLite a un support limité d'ALTER TABLE que vous pouvez utiliser pour ajouter un colonne à la fin d’une table ou pour changer le nom d’une table. Si vous voulez faire des changements plus complexes dans la structure d'une table, vous devra recréer la table. Vous pouvez enregistrer des données existantes dans un fichier table temporaire, supprimez l'ancienne table, créez la nouvelle table, puis copiez les données de la table temporaire.

Par exemple, supposons que vous ayez une table nommée "t1" avec des noms de colonnes "a", "b" et "c" et que vous souhaitez supprimer la colonne "c" de celui-ci table. Les étapes suivantes illustrent comment cela pourrait être réalisé:

BEGIN TRANSACTION;
CREATE TEMPORARY TABLE t1_backup(a,b);
INSERT INTO t1_backup SELECT a,b FROM t1;
DROP TABLE t1;
CREATE TABLE t1(a,b);
INSERT INTO t1 SELECT a,b FROM t1_backup;
DROP TABLE t1_backup;
COMMIT;
170
MeBigFatGuy

Au lieu de supprimer la table de sauvegarde, il suffit de la renommer ...

BEGIN TRANSACTION;
CREATE TABLE t1_backup(a,b);
INSERT INTO t1_backup SELECT a,b FROM t1;
DROP TABLE t1;
ALTER TABLE t1_backup RENAME TO t1;
COMMIT;
51
Duda

Pour plus de simplicité, pourquoi ne pas créer la table de sauvegarde à partir de l'instruction select?

CREATE TABLE t1_backup AS SELECT a, b FROM t1;
DROP TABLE t1;
ALTER TABLE t1_backup RENAME TO t1;
33
user4086833

http://lists.osgeo.org/pipermail/grass-user/2006-January/031981.html

Il existe également un outil appelé Sqliteman qui fournit une option visuelle pour supprimer des colonnes.

Merci, Jignesh

7
Jignesh Gohel

=> Créez une nouvelle table directement avec la requête suivante:

CREATE TABLE Table_name (Column_1 text,Column_2 text);

=> Maintenant, insérez les données dans nom_table à partir de la table Existing_table avec la requête suivante:

insert into Table_name (Column_1,Column_2) FROM Existing_Table;

=> Maintenant, supprimez la table Existing_table en suivant la requête:

DROP Existing_Table;
3
user3317939

Cette option ne fonctionne que si vous pouvez ouvrir la base de données dans un navigateur de base de données tel que DB Browser for SQLite .

Dans le navigateur de base de données pour SQLite:

  1. Allez sur l'onglet "Structure de la base de données" 
  2. Sélectionnez votre table Sélectionnez Modifier la table (juste sous les onglets)
  3. Sélectionnez la colonne que vous souhaitez supprimer
  4. Cliquez sur le champ Supprimer et cliquez sur OK
3
MagTun

Pour SQLite3 c ++:

void GetTableColNames( tstring sTableName , std::vector<tstring> *pvsCols )
{
    UASSERT(pvsCols);

    CppSQLite3Table table1;

    tstring sDML = StringOps::std_sprintf(_T("SELECT * FROM %s") , sTableName.c_str() );



    table1 = getTable( StringOps::tstringToUTF8string(sDML).c_str() );

    for ( int nCol = 0 ; nCol < table1.numFields() ; nCol++ )
    {
        const char* pch1 = table1.fieldName(nCol);  

        pvsCols->Push_back( StringOps::UTF8charTo_tstring(pch1));
    }
}


bool ColExists( tstring sColName )
{
    bool bColExists = true;

    try
    {
        tstring sQuery = StringOps::std_sprintf(_T("SELECT %s FROM MyOriginalTable LIMIT 1;") , sColName.c_str() );

        ShowVerbalMessages(false);

        CppSQLite3Query q = execQuery( StringOps::tstringTo_stdString(sQuery).c_str() );

        ShowVerbalMessages(true);
    }
    catch (CppSQLite3Exception& e)
    {
        bColExists = false;
    }

    return bColExists;
}

void DeleteColumns( std::vector<tstring> *pvsColsToDelete )
{
    UASSERT(pvsColsToDelete);

    execDML( StringOps::tstringTo_stdString(_T("begin transaction;")).c_str() );


    std::vector<tstring> vsCols;
    GetTableColNames( _T("MyOriginalTable") , &vsCols );


    CreateFields( _T("TempTable1") , false );

    tstring sFieldNamesSeperatedByCommas;

    for ( int nCol = 0 ; nCol < vsCols.size() ; nCol++ )
    {

        tstring sColNameCurr = vsCols.at(nCol);

        bool bUseCol = true;

        for ( int nColsToDelete = 0; nColsToDelete < pvsColsToDelete->size() ; nColsToDelete++ )
        {
            if ( pvsColsToDelete->at(nColsToDelete) == sColNameCurr )
            {
                bUseCol = false;
                break;
            }
        }

        if ( bUseCol )
            sFieldNamesSeperatedByCommas+= (sColNameCurr + _T(","));

    }

    if ( sFieldNamesSeperatedByCommas.at( int(sFieldNamesSeperatedByCommas.size()) - 1) == _T(','))
        sFieldNamesSeperatedByCommas.erase( int(sFieldNamesSeperatedByCommas.size()) - 1 );

    tstring sDML;


    sDML = StringOps::std_sprintf(_T("insert into TempTable1 SELECT %s FROM MyOriginalTable;\n") , sFieldNamesSeperatedByCommas.c_str() );
    execDML( StringOps::tstringTo_stdString(sDML).c_str() );

    sDML = StringOps::std_sprintf(_T("ALTER TABLE MyOriginalTable RENAME TO MyOriginalTable_old\n") );
    execDML( StringOps::tstringTo_stdString(sDML).c_str() );

    sDML = StringOps::std_sprintf(_T("ALTER TABLE TempTable1 RENAME TO MyOriginalTable\n") );
    execDML( StringOps::tstringTo_stdString(sDML).c_str() );


    sDML = ( _T("DROP TABLE MyOriginalTable_old;") );   
    execDML( StringOps::tstringTo_stdString(sDML).c_str() );


    execDML( StringOps::tstringTo_stdString(_T("commit transaction;")).c_str() );   
}
1
Sunny127

Dans le cas où quelqu'un aurait besoin d'une fonction PHP prête à être utilisée, voici ce qui suit basé sur cette réponse :

/**
 * Remove a column from a table.
 * 
 * @param string $tableName The table to remove the column from.
 * @param string $columnName The column to remove from the table.
 */
public function DropTableColumn($tableName, $columnName)
{
    // --
    // Determine all columns except the one to remove.

    $columnNames = array();

    $statement = $pdo->prepare("PRAGMA table_info($tableName);");
    $statement->execute(array());
    $rows = $statement->fetchAll(PDO::FETCH_OBJ);

    $hasColumn = false;

    foreach ($rows as $row)
    {
        if(strtolower($row->name) !== strtolower($columnName))
        {
            array_Push($columnNames, $row->name);
        }
        else
        {
            $hasColumn = true;
        }
    }

    // Column does not exist in table, no need to do anything.
    if ( !$hasColumn ) return;

    // --
    // Actually execute the SQL.

    $columns = implode('`,`', $columnNames);

    $statement = $pdo->exec(
       "CREATE TABLE `t1_backup` AS SELECT `$columns` FROM `$tableName`;
        DROP TABLE `$tableName`;
        ALTER TABLE `t1_backup` RENAME TO `$tableName`;");
}

Contrairement à d'autres réponses, le code SQL utilisé dans cette approche semble conserver les types de données des colonnes, alors que quelque chose comme la réponse acceptée semble avoir pour résultat que toutes les colonnes sont de type TEXT.

Mise à jour 1:

Le code SQL utilisé présente l'inconvénient que les colonnes autoincrement sont conservées non.

0
Uwe Keim