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

Android Kotlin中SQLite执行INSERT语句后行计数递增但数据未实际插入表中

Android Kotlin中SQLite执行INSERT语句后行计数递增但数据未实际插入表中

看起来你遇到的这个问题很典型,我帮你梳理下可能的原因和对应的解决办法:


1. 最可能的核心问题:表名不匹配

你创建表的语句明确指定了表名为 ReaderFlag:

CREATE TABLE IF NOT EXISTS ReaderFlag (
    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    reader_customer_id INTEGER NOT NULL,
    reader_route_id INTEGER NOT NULL,
    start_end_flag TEXT NOT NULL
);

但插入操作的目标表是 $Reader_Table 这个常量。请立刻确认 Reader_Table 的值是否严格等于 "ReaderFlag"。如果两者不一致,你其实是在往一个错误的表(甚至是SQLite自动创建的临时表)插入数据,而你查看的ReaderFlag表自然是空的。

2. 手动拼接SQL的风险与错误

你当前用字符串拼接的方式构造INSERT语句,这种做法很容易引发各种隐性问题:

  • 特殊字符转义错误:比如action.address里如果包含引号、反斜杠,会直接破坏SQL语法,导致插入失败(目前测试数据可能没这类字符,但隐患一直存在)
  • 字段值不符合业务逻辑:比如如果action.start和action.stop同时为false,flagString会是空字符串——虽然空字符串满足NOT NULL约束,但这是否符合你的业务需求?
  • 代码可读性差,排查问题困难

3. 推荐的正确做法:使用ContentValues + insertOrThrow

你之前注释掉的ContentValues方案才是Android SQLite官方推荐的安全插入方式,它会自动处理字符串转义、字段类型匹配,还能通过insertOrThrow抛出明确的异常信息帮你快速定位问题。修改后的代码如下:

fun uploadFlagToCustomer(
    database: SQLiteDatabase,
    flags: List<StartStopPremisesFlag>
) {
    flags.forEach { action ->
        // 更简洁的flag字符串转换逻辑
        val flagString = when {
            action.start -> "start"
            action.stop -> "stop"
            else -> "" // 这里建议根据业务需求处理,比如抛出异常或设置默认值
        }

        val contentValues = ContentValues().apply {
            // 请确保ReaderTable的常量与数据表字段完全对应
            put(ReaderTable.startEndFlag, flagString)
            put(ReaderTable.customerID, action.customer)
            put(ReaderTable.routeID, action.route)
            // 注意:如果要插入address字段,你需要先在ReaderFlag表中添加对应的字段(比如reader_customer_address),否则会抛出字段不存在的异常
            // put(ReaderTable.customer_address, action.address.trim())
        }

        try {
            val insertedRowId = database.insertOrThrow(Reader_Table, null, contentValues)
            println("成功插入,行ID:$insertedRowId")
        } catch (e: SQLiteException) {
            println("插入失败:${e.message}")
            e.printStackTrace() // 打印完整栈轨迹,方便定位问题
        }
    }
}

4. 额外验证步骤

为了确认数据是否真的被插入,你可以在插入后立刻查询目标表的行数:

// 在函数末尾或者循环内添加查询
val countCursor = database.rawQuery("SELECT COUNT(*) FROM $Reader_Table", null)
if (countCursor.moveToFirst()) {
    val totalRows = countCursor.getInt(0)
    println("当前表${Reader_Table}的总行数:$totalRows")
}
countCursor.close()

5. 事务相关检查

如果你的代码在调用uploadFlagToCustomer之前开启了事务,但没有正确提交:

// 错误示例:开启事务但未提交
database.beginTransaction()
uploadFlagToCustomer(database, flags)
// 缺少 database.setTransactionSuccessful() 和 database.endTransaction()

这种情况下,所有插入操作都会被回滚,表数据不会被持久化。请确保事务的正确使用:

database.beginTransaction()
try {
    uploadFlagToCustomer(database, flags)
    database.setTransactionSuccessful() // 标记事务成功
} catch (e: Exception) {
    println("事务执行失败:${e.message}")
} finally {
    database.endTransaction() // 结束事务,成功则提交,失败则回滚
}

备注:内容来源于stack exchange,提问作者Jisa Joy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 09:03:07