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.
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;
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;
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;
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
=> 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;
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:
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() );
}
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.