如何在SQLITE中删除或添加列?

San*_*dip 219 sqlite

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

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

ALTER TABLE TABLENAME DROP COLUMN COLUMNNAME
Run Code Online (Sandbox Code Playgroud)

但它给出了错误

System.Data.SQLite.SQLiteException: SQLite error
near "DROP": syntax error
Run Code Online (Sandbox Code Playgroud)

Mic*_*aga 331

ALTER TABLE SQLite

SQLite支持ALTER TABLE的有限子集.SQLite中的ALTER TABLE命令允许用户重命名表或向现有表添加新列.无法重命名列,删除列,或从表中添加或删除约束.

您可以:

  1. 创建新表作为您要更改的表,
  2. 复制所有数据,
  3. 放下旧桌子,
  4. 重命名新的.

  • http://stackoverflow.com/a/5987838/1578528给出了执行任务的基本示例. (44认同)
  • 这个答案已经过时了 - 现在支持“ALTER TABLE tablename DROP COLUMN columnname”。[参见文档](http://www.sqlite.org/lang_altertable.html)。 (4认同)
  • 在执行此序列之前,如果有外部表引用此表,则必须调用`PRAGMA foreign_keys = OFF`.在这种情况下,在执行此序列之后,必须调用`PRAGMA foreign_keys = ON`以重新启用外键. (3认同)
  • 在较新的 SQLite 版本中,支持“RENAME COLUMN”。https://www.sqlite.org/releaselog/3_25_0.html (2认同)

Udi*_*nic 45

我已经编写了一个基于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;");
}
Run Code Online (Sandbox Code Playgroud)

要获取表的列,我使用了"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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 我很确定如果您使用此解决方案,结果表上的列将完全裸露 - 不会保留类型信息,PK,FK,默认值,唯一或检查约束.导入到新表的所有内容都是列名.此外,由于它在运行之前不会禁用外键,因此其他表中的数据也会被搞砸. (3认同)
  • 或者,您也可以通过执行`"CREAT TABLE"+ tableName +"AS SELECT"+ columnsSeperated +"FROM"+ tableName +"_ old;"来创建新表,而不是执行`INSERT`语句. (3认同)
  • 如果这是在单个事务中完成的,而不是可能允许其他代码看到处于过渡状态的事情,那会更好. (2认同)

Tas*_*man 19

正如其他人所指出的那样

无法重命名列,删除列,或从表中添加或删除约束.

来源:http://www.sqlite.org/lang_altertable.html

虽然您可以随时创建一个新表,然后删除旧表.我将尝试用一个例子来解释这个解决方法.

sqlite> .schema
CREATE TABLE person(
 id INTEGER PRIMARY KEY, 
 first_name TEXT,
 last_name TEXT, 
 age INTEGER, 
 height INTEGER
);
sqlite> select * from person ; 
id          first_name  last_name   age         height    
----------  ----------  ----------  ----------  ----------
0           john        doe         20          170       
1           foo         bar         25          171       
Run Code Online (Sandbox Code Playgroud)

现在您要height从此表中删除该列.

创建另一个名为的表 new_person

sqlite> CREATE TABLE new_person(
   ...>  id INTEGER PRIMARY KEY, 
   ...>  first_name TEXT, 
   ...>  last_name TEXT, 
   ...>  age INTEGER 
   ...> ) ; 
sqlite> 
Run Code Online (Sandbox Code Playgroud)

现在复制旧表中的数据

sqlite> INSERT INTO new_person
   ...> SELECT id, first_name, last_name, age FROM person ;
sqlite> select * from new_person ;
id          first_name  last_name   age       
----------  ----------  ----------  ----------
0           john        doe         20        
1           foo         bar         25        
sqlite>
Run Code Online (Sandbox Code Playgroud)

现在删除person表并重命名new_personperson

sqlite> DROP TABLE IF EXISTS person ; 
sqlite> ALTER TABLE new_person RENAME TO person ;
sqlite>
Run Code Online (Sandbox Code Playgroud)

所以现在如果你做了.schema,你会看到

sqlite>.schema
CREATE TABLE "person"(
 id INTEGER PRIMARY KEY, 
 first_name TEXT, 
 last_name TEXT, 
 age INTEGER 
);
Run Code Online (Sandbox Code Playgroud)

  • 我可以说你是一个真正的程序员.约翰·多伊之后你的名字用完了,直奔"foo bar":) (6认同)
  • `CREATE TABLE new_person AS SELECT id, first_name, last_name, age FROM person;` (2认同)

and*_*otn 19

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

\n

但现在这些功能都已支持,您所需要做的就是升级 SQLite。

\n\n

请注意,仍然存在一些边缘情况,这些可能不起作用,例如,您无法删除主键列。请参阅文档了解更多详细信息。当这些ALTER TABLE \xe2\x80\xa6 COLUMN语句不起作用时,您可以退回到四步过程。

\n

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

\n


ram*_*ams 14

SQLite 的 DB Browser允许您添加或删除列。

在主视图 tab 中Database Structure,单击表名。一个按钮Modify Table被启用,这会打开一个新窗口,您可以在其中选择列/字段并将其删除。

  • 我想知道如果底层 sqlite3 引擎不支持`ALTER TABLE table_name DROP COLUMN column_name`,它会怎么做 (3认同)
  • 在底层,DB Browser for SQLite 使用相同的技术创建临时表/从原始表插入临时表/删除原始表。使用 PRAGMA defer_foreign_keys 推迟外键验证 (2认同)

Lel*_*mbo 12

http://www.sqlite.org/lang_altertable.html

如图所示,仅支持ADD COLUMN.但是有一种(有点重)解决方法:http://www.sqlite.org/faq.html#q11


Luk*_*zda 12

SQLite 3.35.0 引入了对ALTER TABLE DROP COLUMN.

更改表

DROP COLUMN 语法用于从表中删除现有列。DROP COLUMN 命令从表中删除命名列,并重写整个表以清除与该列关联的数据。DROP COLUMN 命令仅在该列未被架构的任何其他部分引用并且不是 PRIMARY KEY 并且没有 UNIQUE 约束时才有效。

以下语法将有效:

ALTER TABLE <TABLENAME> DROP COLUMN <COLUMNNAME>;
ALTER TABLE <TABLENAME> DROP <COLUMNNAME>;
Run Code Online (Sandbox Code Playgroud)

  • 很酷,但是 Android 何时会接受该语法? (5认同)
  • @Sergio 目前看来最高版本是[3.32.2](/sf/answers/306398151/)。不知道什么时候升级。 (4认同)
  • 在这里您可以了解Android API级别使用哪个版本的Sqlite:https://developer.android.com/reference/android/database/sqlite/package-summary (3认同)
  • 所以根据文档中提到的sqlite版本,我们不能在Android设备上使用这个语法! (3认同)