如何在Android Studio中使用Room为SQLite编写需要参数的查询?

huangapple go评论63阅读模式
英文:

How can I write a query which require parameter for SQLite with Room in Android Studio?

问题

I know I can use Code A to accept a parameter for id
我知道我可以使用代码A来接受一个id参数

I hope to accept an order by parameter in Code B, how can I do?
我希望在代码B中接受一个order by参数,我该如何做?

You know there are four methods for order by, there are:
你知道有四种用于order by的方法,它们分别是:

SELECT * FROM info_table ORDER BY createdDate desc
SELECT * FROM info_table ORDER BY createdDate asc
SELECT * FROM info_table ORDER BY title desc
SELECT * FROM info_table ORDER BY title asc

Code A
代码A

@Query("SELECT * FROM info_table where id=:id")
suspend fun getByID(id:Int): RecordEntity

Code B
代码B

@Query("SELECT * FROM info_table ORDER BY createdDate desc")
fun listAll(): Flow<List>

英文:

I know I can use Code A to a accept a parameter for id

I hope to accept a order by parameter in Code B, how can I do?

You know there are four methods for order by , there are :

SELECT * FROM info_table ORDER BY createdDate desc
SELECT * FROM info_table ORDER BY createdDate asc
SELECT * FROM info_table ORDER BY title desc
SELECT * FROM info_table ORDER BY title asc

Code A

@Query(&quot;SELECT * FROM info_table where id=:id&quot;)
suspend fun getByID(id:Int): RecordEntity

Code B

@Query(&quot;SELECT * FROM info_table ORDER BY createdDate desc&quot;)
fun listAll(): Flow&lt;List&lt;RecordEntity&gt;&gt;

答案1

得分: 2

以下是要翻译的内容:

有基本上3种方法可以做到这一点。

  • 第四种方法,使用CTE,可以在https://stackoverflow.com/questions/76278049/how-can-i-add-the-sencond-sort-item-when-i-use-case-to-require-parameter-for-sql/76285491#76285491找到

选项1.

为每个选项有4个带有@Query注释的函数,然后有第5个函数,根据参数调用4个函数中的相应函数。 (选项3使用4个选项的替代数值表示)

例如,

@Query("SELECT * FROM info_table ORDER BY createdDate desc")
fun selectOption1(): List<RecordEntity>
@Query("SELECT * FROM info_table ORDER BY createdDate asc")
fun selectOption2(): List<RecordEntity>
@Query("SELECT * FROM info_table ORDER BY createdDate desc")
fun selectOption3(): List<RecordEntity>
fun selectOption4(): Flow<List<RecordEntity>>
fun selectAppropriateOption(orderColumn: String, ifASC: Boolean): Flow<List<RecordEntity>> {
    if (orderColumn.equals("createdDate"))
        if (ifASC) {
            return selectOption2()
        } else {
            return selectOption1()
        }
    if (orderColumn.equals("title"))
        if (ifASC) {
            return selectOption4()
        } else {
            return selectOption3()
        }
    /* 处理不是orderColumn的情况???? */
    return selectOption1() /* 例如默认 */
}

选项2. 使用@RawQuery

有类似以下的内容:-

@RawQuery
fun rq(query: SimpleSQLiteQuery): List<RecordEntity>
fun selectViaRawQuery(orderColumn: String, ifASC: Boolean): Flow<List<RecordEntity>> {
    var orderType = " ASC "
    if (!ifASC) orderType = " DESC "
    return flow { emit(rq(SimpleSQLiteQuery("SELECT * FROM info_table ORDER BY $orderColumn $orderType"))) }
}
  • 注意 Room无法在编译时检查查询的有效性,因此有更大的运行时错误的机会。

选项3.

最后一种选择是利用CASE WHEN THEN ELSE END结构。这个答案与你的问题非常相似(有2列和两种排序类型)。

例如,

@Query(
    "SELECT * FROM info_table ORDER BY " +
            "CASE WHEN :parameter = 0 THEN createdDate END DESC, " +
            "CASE WHEN :parameter = 1 THEN createdDate END ASC, " +
            "CASE WHEN :parameter = 2 THEN title END DESC, " +
            "CASE WHEN :parameter = 3 THEN title END ASC"
)
fun selectViaCase(/*childId: Int,*/ parameter: Int): Flow<List<RecordEntity>>

上述所有内容都经过了测试(编译和运行),但在主线程上,因此没有挂起或等效的操作。

英文:

There are basically 3 ways that you can do this.

Option 1.

Have 4 @Query annotated functions for each option and then have a 5th function that invokes the respective function of the 4 based upon parameters. (option 3 uses an alternative numeric representation for the 4 options)

e.g.

@Query(&quot;SELECT * FROM info_table ORDER BY createdDate desc&quot;)
fun selectOption1(): List&lt;RecordEntity&gt;
@Query(&quot;SELECT * FROM info_table ORDER BY createdDate asc&quot;)
fun selectOption2(): List&lt;RecordEntity&gt;
@Query(&quot;SELECT * FROM info_table ORDER BY createdDate desc&quot;)
fun selectOption3(): List&lt;RecordEntity&gt;
fun selectOption4(): Flow&lt;List&lt;RecordEntity&gt;&gt;
fun selectAppropriateOption(orderColumn: String, ifASC: Boolean): Flow&lt;List&lt;RecordEntity&gt;&gt; {
    if (orderColumn.equals(&quot;createdDate&quot;))
        if (ifASC) {
            return selectOption2()
        } else {
            return selectOption1()
        }
    if (orderColumn.equals(&quot;title&quot;))
        if (ifASC) {
            return selectOption4()
        } else {
            return selectOption3()
        }
    /* handle neither orderColumn????? */
    return selectOption1() /* e.g. default */
}

Option 2. using @RawQuery

Have something along the lines of:-

@RawQuery
fun rq(query: SimpleSQLiteQuery): List&lt;RecordEntity&gt;
fun selectViaRawQuery(orderColumn: String, ifASC: Boolean): Flow&lt;List&lt;RecordEntity&gt;&gt; {
    var orderType = &quot; ASC &quot;
    if (!ifASC) orderType = &quot; DESC &quot;
    return flow { emit(rq(SimpleSQLiteQuery(&quot;SELECT * FROM info_table ORDER BY $orderColumn $orderType&quot;))) }
}
  • Noting that Room cannot check the validity of the query at compile time and thus there is the greater chance of a run time error.

Option 3.

The last option is to utilise the CASE WHE THEN ELSE END construct. This answer is very much the same as for your question (2 columns and both order types).

e.g.

@Query(
    &quot;SELECT * FROM info_table ORDER BY &quot; +
            &quot;CASE WHEN :parameter = 0 THEN createdDate END DESC, &quot; +
            &quot;CASE WHEN :parameter = 1 THEN createdDate END ASC, &quot; +
            &quot;CASE WHEN :parameter = 2 THEN title END DESC, &quot; +
            &quot;CASE WHEN :parameter = 3 THEN title END ASC&quot;
)
fun selectViaCase(/*childId: Int,*/ parameter: Int): Flow&lt;List&lt;RecordEntity&gt;&gt;

All the above have been tested (compiled and run), but on the main thread and hence no suspend or equivalent.

huangapple
  • 本文由 发表于 2023年5月13日 15:51:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76241639.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定