如何使用@RawQuery获取房间数据库中受影响的行

问题描述 投票:0回答:1

我使用 @RawQuery 在房间数据库中执行查询。但我找不到一种方法来以这种方式获取受影响的行。

我尝试了

SELECT changes() as affected_rows
并通过光标获取结果,但它总是返回零。

到目前为止我的代码(我在插入、更新、删除语句后运行此代码)。

val cursor = daoUnit.query(SimpleSQLiteQuery("SELECT CHANGES() AS affected_rows"))
var affectedRowCount = 0
   cursor.use { innerCursor ->
        val affectedRowColumn = innerCursor.getColumnIndex("affected_rows")

        if (innerCursor.count > 0 && innerCursor.moveToFirst()){
             affectedRowCount = innerCursor.getInt(affectedRowColumn)
             Log.e("TAG", "AFFECTED ROW COUNT : $affectedRowCount")
       }
}
android kotlin sqlite android-room
1个回答
0
投票

我相信您在尝试使用

changes()
函数时不会有任何运气,这可能是由于代码的底层包装所致。

到目前为止我的代码(我在插入、更新、删除语句后运行此代码)

如果您使用便捷方法,即

@Insert
@Update
@Delete
,那么这些返回值可用于确定更改数量。

  • 如下所示,如果不使用便捷方法,则无法获得受影响的行数。

@Update
@Delete
直接以 Int 形式返回受影响的行数。

@Insert
,如果在可以处理插入的多行的插入的情况下未插入行,则返回 rowid 或 -1,然后返回 rowid 或 -1 的数组。因此,可以通过返回来确定受影响的行数。

作为示例,请考虑以下代码:- 0

  1. 首先是
    @Dao
    带注释的界面中的一些功能

:-

@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(parent: List<Parent>): LongArray

@RawQuery
fun rq(sql: SupportSQLiteQuery): Cursor

@Query("INSERT INTO parent VALUES (100,'XP1'),(null,'XP2')")
fun insertViaSQL()

@Transaction
@Query("")
fun xxx() {
    val result = insert(listOf(Parent(parent_name = "PARENT1"),Parent(parent_name = "PARENT2")))
    DatabaseUtils.dumpCursor(rq(SimpleSQLiteQuery("SELECT changes() AS affected_rows")))
    var skipped=0
    var inserted = 0
    for (r in result) {
        if (r == -1L) skipped++ else inserted++
    }
    Log.d("DBINFO","Inserted ${inserted}. Skipped ${skipped}")
    rq(SimpleSQLiteQuery("INSERT INTO parent VALUES (100,'XP1'),(null,'XP2')"))
    DatabaseUtils.dumpCursor(rq(SimpleSQLiteQuery("SELECT changes() AS affected_rows")))

}
  1. 然后是一些活动代码

:-

    val parents: ArrayList<Parent> = ArrayList()
    val sql1: SupportSQLiteQuery = SimpleSQLiteQuery("SELECT CHANGES() AS affected_rows")
    val sql2 = SimpleSQLiteQuery("SELECT (CHANGES()) AS affected_rows")
    parents.add(Parent(parent_name = "P1"))
    parents.add(Parent(parent_name = "P2"))
    parents.add(Parent(parent_name = "P3"))
    parents.add(Parent(parent_name = "P4"))
    parents.add(Parent(1,"rowid 1 would likely already exist"))
    val result = dao.insert(parents)
    var skipped=0
    var inserted=0
    for (rslt in result) {
        if (rslt == -1L) skipped++ else inserted++
    }
    Log.d("DBINFO","Inserted ${inserted}, Skipped ${skipped}")
    insertViaSQL()
    val csr = dao.rq(sql1)
    DatabaseUtils.dumpCursor(csr)
    DatabaseUtils.dumpCursor(dao.rq(sql2))
    dao.xxx()
  • sql2 消除了更改函数不在括号内的可能性(正如我们将看到的那样,它不是)。
  • 4 尝试通过插入多个对象/行的插入将 5 行插入父表中。注意到最后一个有一个值应该会导致插入由于 UNIQUE 冲突而被忽略。然后使用生成的 LongArray 捕获插入的行数和未插入(跳过)的行数。结果写入日志。
    • 预期结果是插入 4 个,跳过 1 个。
  • 进行了 2 次尝试来获取转储到日志的返回游标的更改数量(受影响的行)。
  • 最后调用xxx函数。首先尝试插入两行,紧接着原始查询以获取更改,并将生成的游标转储到日志中。
    • 从插入中获得的结果也会写入日志(插入 2 行,跳过 0 行)
  • xxx 函数继续并尝试插入 2 行,但通过 INSERT sql,而不是方便的
    @Insert
    方法。这是原始 SQL,不会返回任何结果。但是,由于 Room 确定不会返回任何结果,因此不会执行原始查询。
  • 由于未执行原始查询,因此调用 insertViaSQL 函数,这会尝试 2 次插入。
  • xxx 函数然后尝试通过将结果游标转储到日志中来获取更改数量。
    
    
  • 日志包括:-

@RawQuery

可以看出,
2024-09-24 15:55:19.159 D/DBINFO: Inserted 4, Skipped 1 2024-09-24 15:55:19.159 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@649c946 2024-09-24 15:55:19.160 I/System.out: 0 { 2024-09-24 15:55:19.160 I/System.out: affected_rows=0 2024-09-24 15:55:19.160 I/System.out: } 2024-09-24 15:55:19.160 I/System.out: <<<<< 2024-09-24 15:55:19.160 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@ae23707 2024-09-24 15:55:19.161 I/System.out: 0 { 2024-09-24 15:55:19.161 I/System.out: affected_rows=0 2024-09-24 15:55:19.161 I/System.out: } 2024-09-24 15:55:19.161 I/System.out: <<<<< 2024-09-24 15:55:19.180 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@57fc034 2024-09-24 15:55:19.180 I/System.out: 0 { 2024-09-24 15:55:19.180 I/System.out: affected_rows=0 2024-09-24 15:55:19.180 I/System.out: } 2024-09-24 15:55:19.180 I/System.out: <<<<< 2024-09-24 15:55:19.180 D/DBINFO: Inserted 2. Skipped 0 2024-09-24 15:55:19.182 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@2cde5d 2024-09-24 15:55:19.182 I/System.out: 0 { 2024-09-24 15:55:19.182 I/System.out: affected_rows=0 2024-09-24 15:55:19.182 I/System.out: } 2024-09-24 15:55:19.182 I/System.out: <<<<<

的返回值(LongArray)可用于确定受影响的行数。但是,

@Insert
内置函数在任何时候都不会返回 0 以外的值,即使在与后者插入尝试相同的事务中也是如此。
显然 

changes()

@Delete
更简单,因为返回的是受影响的行数。
    

© www.soinside.com 2019 - 2024. All rights reserved.