我想在sqlite数据库中删除或添加列

我正在使用以下查询删除列。

ALTER TABLE TABLENAME DROP COLUMN COLUMNNAME

但它会产生错误

System.Data.SQLite.SQLiteException: SQLite error
near "DROP": syntax error

当前回答

在SQLite 3中不能删除特定的列。参见FAQ。

其他回答

有一段时间不直接支持这一点,您需要遵循以下四个步骤:(1)创建一个temporary_table,(2)复制数据,(3)删除旧表,然后(4)重命名temporary_table。

但是现在支持这些特性,您所需要做的就是升级SQLite。

3.35.0 from 2021-03-12添加ALTER TABLE DROP COLUMN 3.25.0 from 2018-09-15新增ALTER TABLE RENAME COLUMN 3.2.0在2005-03-21添加了ALTER TABLE ADD COLUMN

请注意,仍然有一些边缘情况下,这些可能不起作用,例如,您不能删除主键列。有关详细信息,请参阅文档。当这些ALTER TABLE…COLUMN语句不起作用时,您可以退回到四步过程。

顺便说一下,文档中的四步流程实际上是十二步流程。但其中四个步骤非常重要,很容易出错,在这些文档中特别指出。

我根据Sqlite推荐的方法写了一个Java实现:

private void dropColumn(SQLiteDatabase db,
        ConnectionSource connectionSource,
        String createTableCmd,
        String tableName,
        String[] colsToRemove) throws java.sql.SQLException {

    List<String> updatedTableColumns = getTableColumns(tableName);
    // Remove the columns we don't want anymore from the table's list of columns
    updatedTableColumns.removeAll(Arrays.asList(colsToRemove));

    String columnsSeperated = TextUtils.join(",", updatedTableColumns);

    db.execSQL("ALTER TABLE " + tableName + " RENAME TO " + tableName + "_old;");

    // Creating the table on its new format (no redundant columns)
    db.execSQL(createTableCmd);

    // Populating the table with the data
    db.execSQL("INSERT INTO " + tableName + "(" + columnsSeperated + ") SELECT "
            + columnsSeperated + " FROM " + tableName + "_old;");
    db.execSQL("DROP TABLE " + tableName + "_old;");
}

为了获得表的列,我使用了“PRAGMA table_info”:

public List<String> getTableColumns(String tableName) {
    ArrayList<String> columns = new ArrayList<String>();
    String cmd = "pragma table_info(" + tableName + ");";
    Cursor cur = getDB().rawQuery(cmd, null);

    while (cur.moveToNext()) {
        columns.add(cur.getString(cur.getColumnIndex("name")));
    }
    cur.close();

    return columns;
}

实际上我在我的博客上写过,你可以在那里看到更多的解释:

http://udinic.wordpress.com/2012/05/09/sqlite-drop-column-support/

基于http://www.sqlite.org/faq.html#q11上的信息在Python中实现。

import sqlite3 as db
import random
import string

QUERY_TEMPLATE_GET_COLUMNS = "PRAGMA table_info(@table_name)"
QUERY_TEMPLATE_DROP_COLUMN = """
  BEGIN TRANSACTION;
  CREATE TEMPORARY TABLE @tmp_table(@columns_to_keep);
  INSERT INTO @tmp_table SELECT @columns_to_keep FROM @table_name;
  DROP TABLE @table_name;
  CREATE TABLE @table_name(@columns_to_keep);
  INSERT INTO @table_name SELECT @columns_to_keep FROM @tmp_table;
  DROP TABLE @tmp_table;
  COMMIT;
"""

def drop_column(db_file, table_name, column_name):
    con = db.connect(db_file)
    QUERY_GET_COLUMNS = QUERY_TEMPLATE_GET_COLUMNS.replace("@table_name", table_name)
    query_res = con.execute(QUERY_GET_COLUMNS).fetchall()
    columns_list_to_keep = [i[1] for i in query_res if i[1] != column_name]
    columns_to_keep = ",".join(columns_list_to_keep)
    tmp_table = "tmp_%s" % "".join(random.sample(string.ascii_lowercase, 10))
    QUERY_DROP_COLUMN = QUERY_TEMPLATE_DROP_COLUMN.replace("@table_name", table_name)\
        .replace("@tmp_table", tmp_table).replace("@columns_to_keep", columns_to_keep)
    con.executescript(QUERY_DROP_COLUMN)
    con.close()

drop_column(DB_FILE, TABLE_NAME, COLUMN_NAME)

这个脚本首先创建随机的临时表,并只插入必要列的数据,除了将要删除的列。然后根据临时表恢复原表,删除临时表。

作为替代:

如果有一个带模式的表

CREATE TABLE person(
  id INTEGER PRIMARY KEY,
  first_name TEXT,
  last_name TEXT,
  age INTEGER,
  height INTEGER
);

你可以使用CREATE TABLE…AS语句,如CREATE TABLE person2 AS SELECT id, first_name, last_name, age FROM person;,即去掉你不想要的列。然后删除原来的person表并重命名新表。

注意,此方法生成的表没有PRIMARY KEY,也没有约束。为了保留这些表,可以使用其他人描述的方法来创建新表,或者使用临时表作为中间表。

修改表SQLite

SQLite支持ALTER TABLE的一个有限子集。SQLite中的ALTER TABLE命令允许用户重命名表或向现有表添加新列。不能重命名列、删除列或从表中添加或删除约束。

您可以:

创建新表作为您要更改的表, 复制所有数据, 丢掉旧桌子, 重新命名新文件。