如何在SQLITE中删除或添加列?
我想在sqlite数据库中删除或添加列
我正在使用以下查询来删除列。
ALTER TABLE TABLENAME DROP COLUMN DIST_TYPE
但它给错误
System.Data.SQLite.SQLiteException: SQLite error near "DROP": syntax error
ALTER TABLE SQLite
SQLite支持ALTER TABLE的有限子集。 SQLite中的ALTER TABLE命令允许用户重命名表或向现有表添加新列。 不能重命名列,删除列或添加或删除表中的约束。
您可以:
- 创build新的表格作为您正在尝试更改的表格,
- 复制所有数据,
- 放下旧桌子,
- 重命名新的。
我已经写了一个基于Sqlitebuild议的方式来执行此操作的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/lang_altertable.html
正如您在图中看到的那样,仅支持ADD COLUMN。 有一个(有点沉重)解决方法,但: http : //www.sqlite.org/faq.html#q11
正如其他人指出的那样
不能重命名列,删除列或添加或删除表中的约束。
来源: http : //www.sqlite.org/lang_altertable.html
虽然你总是可以创build一个新表,然后删除旧的表。 我将尝试用一个例子来解释这个解决方法 。
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
现在你想从这个表中删除列的height
。
创build另一个名为new_person
表
sqlite> CREATE TABLE new_person( ...> id INTEGER PRIMARY KEY, ...> first_name TEXT, ...> last_name TEXT, ...> age INTEGER ...> ) ; sqlite>
现在复制旧表中的数据
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>
现在放下person
表格,并将new_person
重命名为person
sqlite> DROP TABLE IF EXISTS person ; sqlite> ALTER TABLE new_person RENAME TO person ; sqlite>
所以现在如果你做一个.schema
,你会看到
sqlite>.schema CREATE TABLE "person"( id INTEGER PRIMARY KEY, first_name TEXT, last_name TEXT, age INTEGER );
我们不能删除SQLite 3中的特定列。请参阅FAQ 。
正如其他人指出的,sqlite的ALTER TABLE
语句不支持DROP COLUMN
,标准配方这样做并不保留约束和索引。
下面是一些python代码,一般来说这样做,同时保持所有的关键约束和索引。
请在使用前备份您的数据库! 这个函数依赖于修改原来的CREATE TABLE语句,并且可能有点不安全 – 例如,如果标识符包含embedded的逗号或括号,它会做错误的事情。
如果有人愿意提供一个更好的方法来parsingSQL,这将是伟大的!
更新我find了一个更好的方法来parsing使用开源sqlparse
包。 如果有任何兴趣,我会在这里发表,只是留下一个评论,要求它…
import re import random def DROP_COLUMN(db, table, column): columns = [ c[1] for c in db.execute("PRAGMA table_info(%s)" % table) ] columns = [ c for c in columns if c != column ] sql = db.execute("SELECT sql from sqlite_master where name = '%s'" % table).fetchone()[0] sql = format(sql) lines = sql.splitlines() findcol = r'\b%s\b' % column keeplines = [ line for line in lines if not re.search(findcol, line) ] create = '\n'.join(keeplines) create = re.sub(r',(\s*\))', r'\1', create) temp = 'tmp%d' % random.randint(1e8, 1e9) db.execute("ALTER TABLE %(old)s RENAME TO %(new)s" % { 'old': table, 'new': temp }) db.execute(create) db.execute(""" INSERT INTO %(new)s ( %(columns)s ) SELECT %(columns)s FROM %(old)s """ % { 'old': temp, 'new': table, 'columns': ', '.join(columns) }) db.execute("DROP TABLE %s" % temp) def format(sql): sql = sql.replace(",", ",\n") sql = sql.replace("(", "(\n") sql = sql.replace(")", "\n)") return sql
由于SQLite对ALTER TABLE的支持有限,因此您只能在SQLite表的OR CHANGE TABLE_NAME表中添加列。
这里是如何从SQLITE中删除列的最佳答案?
请访问从SQLite表中删除列
我重写了@Udinic答案,以便代码自动生成表创build查询。 它也不需要ConnectionSource
。 它也必须在交易中这样做。
public static String getOneTableDbSchema(SQLiteDatabase db, String tableName) { Cursor c = db.rawQuery( "SELECT * FROM `sqlite_master` WHERE `type` = 'table' AND `name` = '" + tableName + "'", null); String result = null; if (c.moveToFirst()) { result = c.getString(c.getColumnIndex("sql")); } c.close(); return result; } public List<String> getTableColumns(SQLiteDatabase db, String tableName) { ArrayList<String> columns = new ArrayList<>(); String cmd = "pragma table_info(" + tableName + ");"; Cursor cur = db.rawQuery(cmd, null); while (cur.moveToNext()) { columns.add(cur.getString(cur.getColumnIndex("name"))); } cur.close(); return columns; } private void dropColumn(SQLiteDatabase db, String tableName, String[] columnsToRemove) { db.beginTransaction(); try { List<String> columnNamesWithoutRemovedOnes = getTableColumns(db, tableName); // Remove the columns we don't want anymore from the table's list of columns columnNamesWithoutRemovedOnes.removeAll(Arrays.asList(columnsToRemove)); String newColumnNamesSeparated = TextUtils.join(" , ", columnNamesWithoutRemovedOnes); String sql = getOneTableDbSchema(db, tableName); // Extract the SQL query that contains only columns String oldColumnsSql = sql.substring(sql.indexOf("(")+1, sql.lastIndexOf(")")); db.execSQL("ALTER TABLE " + tableName + " RENAME TO " + tableName + "_old;"); db.execSQL("CREATE TABLE `" + tableName + "` (" + getSqlWithoutRemovedColumns(oldColumnsSql, columnsToRemove)+ ");"); db.execSQL("INSERT INTO " + tableName + "(" + newColumnNamesSeparated + ") SELECT " + newColumnNamesSeparated + " FROM " + tableName + "_old;"); db.execSQL("DROP TABLE " + tableName + "_old;"); db.setTransactionSuccessful(); } catch { //Error in between database transaction } finally { db.endTransaction(); } }
您可以使用SQlitepipe理员更改列名称。 右键单击表名并select编辑表。在这里您可以find表结构,您可以轻松地重命名它。
作为备选:
如果你有一个模式表
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
表格并重命名新的person
表格。
注意这个方法产生的表没有PRIMARY KEY,也没有约束。 为了保留这些内容,可以使用其他描述的方法创build一个新表格,或者使用临时表格作为中间表格 。
对另一个问题的回答是面向修改一个列,但是我相信如果你有很多列并且不想手工为你的INSERT语句重新input大部分的话,那么答案的一部分也可以产生一个有用的方法:
https://stackoverflow.com/a/10385666
你可以按照上面的链接转储你的数据库,然后从这个转储中获取“create table”语句和一个“插入”模板,然后按照SQLite常见问题解答条目中的说明“如何添加或删除现有的列在SQLite表“。 (常见问题链接在此页面的其他地方。)
你可以使用Sqlitebrowser。 在浏览器模式下,对于相应的数据库和表,在选项卡数据库结构下,在选项“修改表”后,可以删除相应的列。
例如添加一列:
alter table student add column TOB time;
这里学生是table_name , TOB是要添加的column_name 。
它正在工作和testing。
您现在也可以使用DB浏览器来处理SQLite列
public void DeleteColFromTable(String DbName, String TableName, String ColName){ SQLiteDatabase db = openOrCreateDatabase(""+DbName+"", Context.MODE_PRIVATE, null); db.execSQL("CREATE TABLE IF NOT EXISTS "+TableName+"(1x00dff);"); Cursor c = db.rawQuery("PRAGMA table_info("+TableName+")", null); if (c.getCount() == 0) { } else { String columns1 = ""; String columns2 = ""; while (c.moveToNext()) { if (c.getString(1).equals(ColName)) { } else { columns1 = columns1 + ", " + c.getString(1) + " " + c.getString(2); columns2 = columns2 + ", " + c.getString(1); } if (c.isLast()) { db.execSQL("CREATE TABLE IF NOT EXISTS DataBackup (" + columns1 + ");"); db.execSQL("INSERT INTO DataBackup SELECT " + columns2 + " FROM "+TableName+";"); db.execSQL("DROP TABLE "+TableName+""); db.execSQL("ALTER TABLE DataBackup RENAME TO "+TableName+";"); } } } }
只是调用一个方法
DeleteColFromTable("Database name","Table name","Col name which want to delete");