我有一個問題:我需要從我的SQLite數據庫中刪除一列。我寫了這個查詢從SQLite表中刪除列
alter table table_name drop column column_name
但它不起作用。請幫幫我。
我有一個問題:我需要從我的SQLite數據庫中刪除一列。我寫了這個查詢從SQLite表中刪除列
alter table table_name drop column column_name
但它不起作用。請幫幫我。
來源:http://www.sqlite.org/faq.html:
(11)如何從SQLite中現有的表中添加或刪除列。
SQLite具有有限的ALTER TABLE支持,您可以使用該支持將 列添加到表的末尾或更改表的名稱。如果 想要對錶的結構進行更復雜的更改,那麼 將不得不重新創建表。您可以將現有數據保存到臨時表中,刪除舊錶,創建新表,然後將數據從臨時表中複製回 。
例如,假設您有一個名爲「t1」的表,其列名爲 「a」,「b」和「c」,並且您想從此 表中刪除列「c」。下面的步驟說明如何可以這樣做:
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;
http://lists.osgeo.org/pipermail/grass-user/2006-January/031981.html
還有一個叫Sqliteman提供可視化選項刪除列的工具。
謝謝, Jignesh
你也可以嘗試http://sqlitebrowser.org – Matthieu 2014-10-25 12:27:24
=>直接與下面的查詢創建一個新的表:
CREATE TABLE Table_name (Column_1 text,Column_2 text);
=>現在將數據與以下查詢插入到表名從Existing_table:
insert into Table_name (Column_1,Column_2) FROM Existing_Table;
=>現在通過以下查詢刪除Existing_table:
DROP Existing_Table;
對於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());
}
而不是丟棄的備份表,只是將其重命名......
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;
當你將foregin鍵連接到't1'時,它不會工作。 。 – ephemerr 2017-12-20 12:54:22
爲了簡單,爲什麼不從select語句創建備份表?
CREATE TABLE t1_backup AS SELECT a, b FROM t1;
DROP TABLE t1;
ALTER TABLE t1_backup RENAME TO t1;
如果有人需要一個(幾乎)準備使用的PHP函數,以下是based on this answer:
/**
* 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`;");
}
相較於其他的答案,在這種方法中使用的SQL似乎保留列的數據類型,而像接受的答案似乎導致所有列的類型爲TEXT
。
更新1:
使用的SQL具有以下缺點:autoincrement
列不保留。
此選項僅在您可以在像DB Browser for SQLite這樣的數據庫瀏覽器中打開數據庫時有效。
在DB瀏覽器的SQLite:
+總是閱讀SQLite文檔。當您遇到錯誤時,您會注意到SQL語法中的太多限制和差異。 SQLite文檔很容易理解。不要擔心。 – 2011-05-13 08:00:32
您需要在刪除安全列後執行VACUUM命令;如果沒有抽真空,數據庫文件仍然包含已刪除列的數據。 – jj1bdx 2017-02-14 05:03:48
@ jj1bdx我不認爲它仍然包含數據,但是「未使用的磁盤空間被添加到內部的」自由列表「中並且在下一次插入數據時被重用。磁盤空間不會丟失。它返回到操作系統。「從sqlite3網站引用。 – 2017-08-23 00:49:55