事务提交成功但数据未插入Android .db文件问题排查求助
问题解决:Android中SQLite ATTACH插入数据无生效,但PC端执行正常的问题
核心问题定位
你代码里犯了一个关键错误:用rawQuery()执行INSERT类的写操作。rawQuery()仅用于执行查询语句并返回结果游标,它不会实际执行数据修改类的SQL语句——这就是为什么你看到事务提交日志,但数据根本没插入的原因。PC端用DB浏览器是直接执行完整SQL,所以没问题。
具体修复方案
1. 原生SQLite代码修正
把rawQuery()替换为execSQL()(适合无返回值的写操作):
val appDbFile = context.getDatabasePath("app_database.db") val appdb = SQLiteDatabase.openDatabase(appDbFile.path, null, SQLiteDatabase.OPEN_READWRITE) val insertUniqueVocabsSqlForAppDb = """ ATTACH '${preDbFile.path}' AS preDb; INSERT INTO vocab(word, language_id, parts_json) SELECT DISTINCT B.word, ${Language.ENGLISH.id}, B.parts_json FROM preDb.EnglishVocabs AS B WHERE B.word NOT IN (SELECT A.word FROM vocab A); """.trimIndent() appdb.beginTransactionWithListener(object : SQLiteTransactionListener { override fun onBegin() { Logger.d("on begin") } override fun onCommit() { Logger.d("on commit") } override fun onRollback() { Logger.d("on rollback") } }) try { Logger.d("attached db = ${appdb.attachedDbs}") // 核心修改:用execSQL执行写操作,而非rawQuery appdb.execSQL(insertUniqueVocabsSqlForAppDb) appdb.setTransactionSuccessful() Logger.d("transaction success") } catch (e: Exception) { Logger.e(e.stackTraceToString()) } finally { appdb.endTransaction() appdb.close() }
2. 额外检查点
- 确认
preDbFile的路径正确:如果预填充数据库来自assets目录,必须先将其复制到APP内部存储(比如context.filesDir),不能直接访问assets路径。 - 验证权限:确保APP拥有访问目标数据库文件的权限(内部存储默认无需动态权限,但如果是外部存储需申请
WRITE_EXTERNAL_STORAGE)。
3. SQLDelight适配方案
如果用SQLDelight,需要用execute()方法执行写操作,同时确保事务正确处理:
val driver = AndroidSqliteDriver(AppDatabase.Schema, context, "app_database.db") val database = AppDatabase(driver) database.transaction { try { val attachSql = "ATTACH '${preDbFile.path}' AS preDb" driver.execute(null, attachSql, 0) val insertSql = """ INSERT INTO vocab(word, language_id, parts_json) SELECT DISTINCT B.word, ${Language.ENGLISH.id}, B.parts_json FROM preDb.EnglishVocabs AS B WHERE B.word NOT IN (SELECT A.word FROM vocab A); """.trimIndent() driver.execute(null, insertSql, 0) this.commit() Logger.d("transaction success") } catch (e: Exception) { this.rollback() Logger.e(e.stackTraceToString()) } }
内容的提问来源于stack exchange,提问作者dofire
相关产品推荐
相关产品推荐

