You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

事务提交成功但数据未插入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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 11:35:20