我想在sqlite数据库中删除或添加列
我正在使用以下查询删除列。
ALTER TABLE TABLENAME DROP COLUMN COLUMNNAME
但它会产生错误
System.Data.SQLite.SQLiteException: SQLite error
near "DROP": syntax error
我想在sqlite数据库中删除或添加列
我正在使用以下查询删除列。
ALTER TABLE TABLENAME DROP COLUMN COLUMNNAME
但它会产生错误
System.Data.SQLite.SQLiteException: SQLite error
near "DROP": syntax error
当前回答
至少在3.37.0版本,sqlite3支持DROP COLUMN
其他回答
SQLite 3.35.0引入了对ALTER TABLE DROP COLUMN的支持。
ALTER TABLE DROP COLUMN语法用于从表中删除现有列。DROP COLUMN命令从表中删除指定的列,并重写整个表以清除与该列相关的数据。DROP COLUMN命令仅在列未被模式的任何其他部分引用、不是PRIMARY KEY且没有UNIQUE约束时才有效。
下面的语法是有效的:
ALTER TABLE <TABLENAME> DROP COLUMN <COLUMNNAME>;
ALTER TABLE <TABLENAME> DROP <COLUMNNAME>;
http://www.sqlite.org/lang_altertable.html
正如您在图中看到的,只支持ADD COLUMN。不过,有一个(有点沉重的)变通方法:http://www.sqlite.org/faq.html#q11
我的解,只需要调用这个方法。
public static void dropColumn(SQLiteDatabase db, String tableName, String[] columnsToRemove) throws java.sql.SQLException {
List<String> updatedTableColumns = getTableColumns(db, tableName);
updatedTableColumns.removeAll(Arrays.asList(columnsToRemove));
String columnsSeperated = TextUtils.join(",", updatedTableColumns);
db.execSQL("ALTER TABLE " + tableName + " RENAME TO " + tableName + "_old;");
db.execSQL("CREATE TABLE " + tableName + " (" + columnsSeperated + ");");
db.execSQL("INSERT INTO " + tableName + "(" + columnsSeperated + ") SELECT "
+ columnsSeperated + " FROM " + tableName + "_old;");
db.execSQL("DROP TABLE " + tableName + "_old;");
}
辅助方法获取列:
public static 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;
}
这个不同问题的答案是针对修改列的,但我相信,如果你有很多列,并且不想在INSERT语句中手动重新输入大部分列,部分答案也可以产生有用的方法:
https://stackoverflow.com/a/10385666
您可以按照上面链接中描述的方法转储数据库,然后从该转储中获取“create table”语句和“insert”模板,然后按照SQLite FAQ条目“如何从SQLite中现有的表中添加或删除列”中的说明进行操作。(常见问题在本页其他地方有链接。)
我已经改进了user2638929回答,现在它可以保留列类型,主键,默认值等。
public static void dropColumns(SQLiteDatabase database, String tableName, Collection<String> columnsToRemove){
List<String> columnNames = new ArrayList<>();
List<String> columnNamesWithType = new ArrayList<>();
List<String> primaryKeys = new ArrayList<>();
String query = "pragma table_info(" + tableName + ");";
Cursor cursor = database.rawQuery(query,null);
while (cursor.moveToNext()){
String columnName = cursor.getString(cursor.getColumnIndex("name"));
if (columnsToRemove.contains(columnName)){
continue;
}
String columnType = cursor.getString(cursor.getColumnIndex("type"));
boolean isNotNull = cursor.getInt(cursor.getColumnIndex("notnull")) == 1;
boolean isPk = cursor.getInt(cursor.getColumnIndex("pk")) == 1;
columnNames.add(columnName);
String tmp = "`" + columnName + "` " + columnType + " ";
if (isNotNull){
tmp += " NOT NULL ";
}
int defaultValueType = cursor.getType(cursor.getColumnIndex("dflt_value"));
if (defaultValueType == Cursor.FIELD_TYPE_STRING){
tmp += " DEFAULT " + "\"" + cursor.getString(cursor.getColumnIndex("dflt_value")) + "\" ";
}else if(defaultValueType == Cursor.FIELD_TYPE_INTEGER){
tmp += " DEFAULT " + cursor.getInt(cursor.getColumnIndex("dflt_value")) + " ";
}else if (defaultValueType == Cursor.FIELD_TYPE_FLOAT){
tmp += " DEFAULT " + cursor.getFloat(cursor.getColumnIndex("dflt_value")) + " ";
}
columnNamesWithType.add(tmp);
if (isPk){
primaryKeys.add("`" + columnName + "`");
}
}
cursor.close();
String columnNamesSeparated = TextUtils.join(", ", columnNames);
if (primaryKeys.size() > 0){
columnNamesWithType.add("PRIMARY KEY("+ TextUtils.join(", ", primaryKeys) +")");
}
String columnNamesWithTypeSeparated = TextUtils.join(", ", columnNamesWithType);
database.beginTransaction();
try {
database.execSQL("ALTER TABLE " + tableName + " RENAME TO " + tableName + "_old;");
database.execSQL("CREATE TABLE " + tableName + " (" + columnNamesWithTypeSeparated + ");");
database.execSQL("INSERT INTO " + tableName + " (" + columnNamesSeparated + ") SELECT "
+ columnNamesSeparated + " FROM " + tableName + "_old;");
database.execSQL("DROP TABLE " + tableName + "_old;");
database.setTransactionSuccessful();
}finally {
database.endTransaction();
}
}
PS:这里我使用的是android.arch.persistence.db。支持sqlitedatabase,但你可以很容易地修改它使用android.database.sqlite.SQLiteDatabase