我需要从很大的roomDB(SQLite)表中删除一些列。
根据我的阅读,我无法从现有表中删除列,为此,我需要创建一个新表并复制所需的列(除了我们要删除的列之外)
通过复制到新表,我设法很好地删除了这些列,但是由于缺少foreignKeys和indices,所以迁移不起作用,这样做的干净语法是什么?
这是我在迁移中用于删除某些列的方法:
private static void deleteColumns(SupportSQLiteDatabase database, String tableName, List<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.query(query);
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 + ") + FOREIGN KEY +(trackartist) REFERENCES artist(artistid) ;" );
database.execSQL("INSERT INTO " + tableName + " (" + columnNamesSeparated + ") SELECT "
+ columnNamesSeparated + " FROM " + tableName + "_old;");
database.execSQL("DROP TABLE " + tableName + "_old;");
database.setTransactionSuccessful();
}finally {
database.endTransaction();
}
}
我无法复制外键和索引
对于外键,您可以根据PRAGMA foreign_keys_list(the_table)
的输出来生成它们,这些输出会生成诸如:-]之类的输出>
PRAGMA foreign_keys_list(the_table)
对于indicies
,您可以基于的输出来生成它们,以获取索引名称并检查UNIQUE约束。使用索引名称,然后可以使用PRAGMA index_list(the_table)
例如,下面的代码修改将起作用(关于限制的注释:-
PRAGMA index_info(the_index_name)
一种替代方法,可能比尝试满足所有排列的方法更简单]]
:-
PRAGMA index_info(the_index_name)
以上与运行以上命令的Logged SQL相比:-
免责声明
以上内容并不能满足所有情况,仅用于说明基本技术。该代码确实包含有关限制的注释。但是,还有其他考虑因素,例如部分索引以及WHERE子句,FTS和FK的MATCH列。