我有一个问题:我需要从我的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