我想在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
当前回答
Kotlin解决方案,基于这里,还要:
确保临时表不存在 修复了检查默认值的类型,因为当它是Integer时返回String类型(此处报告了此问题)。 避免在希望删除的列不存在时执行任何操作。
object DbUtil {
/** https://stackoverflow.com/a/51587449/878126 */
@JvmStatic
fun dropColumns(database: SQLiteDatabase, tableName: String,
columnsToRemove: Collection<String>) {
val columnNames: MutableList<String> = ArrayList()
val columnNamesWithType: MutableList<String> = ArrayList()
val primaryKeys: MutableList<String> = ArrayList()
val query = "pragma table_info($tableName);"
val cursor = database.rawQuery(query, null)
val columnDefaultIndex = cursor.getColumnIndex("dflt_value")
val columnNameIndex = cursor.getColumnIndex("name")
val columnTypeIndex = cursor.getColumnIndex("type")
val columnNotNullIndex = cursor.getColumnIndex("notnull")
val columnPrimaryKeyIndex = cursor.getColumnIndex("pk")
val sb = StringBuilder()
var foundColumnsToRemove = false
while (cursor.moveToNext()) {
val columnName = cursor.getString(columnNameIndex)
if (columnsToRemove.contains(columnName)) {
foundColumnsToRemove = true
continue
}
val columnType = cursor.getString(columnTypeIndex)
val isNotNull = cursor.getInt(columnNotNullIndex) == 1
val isPrimaryKey = cursor.getInt(columnPrimaryKeyIndex) == 1
columnNames.add(columnName)
sb.clear()
sb.append("`$columnName` $columnType ")
if (isNotNull)
sb.append(" NOT NULL ")
if (cursor.getType(columnDefaultIndex) != Cursor.FIELD_TYPE_NULL) {
//has default value
when (columnType.uppercase()) {
"INTEGER" -> sb.append(" DEFAULT ${cursor.getInt(columnDefaultIndex)} ")
"TEXT" -> sb.append(" DEFAULT \"${cursor.getString(columnDefaultIndex)}\" ")
"REAL" -> sb.append(" DEFAULT ${cursor.getFloat(columnDefaultIndex)} ")
}
}
columnNamesWithType.add(sb.toString())
if (isPrimaryKey)
primaryKeys.add("`$columnName`")
}
cursor.close()
if (!foundColumnsToRemove)
return
val columnNamesSeparated = TextUtils.join(", ", columnNames)
if (primaryKeys.size > 0)
columnNamesWithType.add("PRIMARY KEY(${TextUtils.join(", ", primaryKeys)})")
val columnNamesWithTypeSeparated = TextUtils.join(", ", columnNamesWithType)
database.beginTransaction()
try {
var newTempTableName: String
var counter = 0
while (true) {
newTempTableName = "${tableName}_old_$counter"
if (!isTableExists(database, newTempTableName))
break
++counter
}
database.execSQL("ALTER TABLE $tableName RENAME TO $newTempTableName;")
database.execSQL("CREATE TABLE $tableName ($columnNamesWithTypeSeparated);")
database.execSQL(
"INSERT INTO $tableName ($columnNamesSeparated) SELECT $columnNamesSeparated FROM $newTempTableName;")
database.execSQL("DROP TABLE ${newTempTableName};")
database.setTransactionSuccessful()
} finally {
database.endTransaction()
}
}
@JvmStatic
fun isTableExists(database: SQLiteDatabase, tableName: String): Boolean {
database.rawQuery(
"select DISTINCT tbl_name from sqlite_master where tbl_name = '$tableName'", null)
?.use {
return it.count > 0
} ?: return false
}
}
其他回答
由于SQLite对ALTER TABLE的支持有限,所以你只能在表的末尾添加列或在SQLite中更改TABLE_NAME。
这里是如何从SQLITE删除列的最佳答案?
从SQLite表中删除列
正如其他人指出的那样
不能重命名列、删除列或添加或 从表中删除约束。
来源: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
现在要从该表中删除列的高度。
创建另一个名为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
);
这个不同问题的答案是针对修改列的,但我相信,如果你有很多列,并且不想在INSERT语句中手动重新输入大部分列,部分答案也可以产生有用的方法:
https://stackoverflow.com/a/10385666
您可以按照上面链接中描述的方法转储数据库,然后从该转储中获取“create table”语句和“insert”模板,然后按照SQLite FAQ条目“如何从SQLite中现有的表中添加或删除列”中的说明进行操作。(常见问题在本页其他地方有链接。)
在SQLite 3中不能删除特定的列。参见FAQ。
作为替代:
如果有一个带模式的表
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,也没有约束。为了保留这些表,可以使用其他人描述的方法来创建新表,或者使用临时表作为中间表。