英文:
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("SELECT * FROM info_table where id=:id")
suspend fun getByID(id:Int): RecordEntity
Code B
@Query("SELECT * FROM info_table ORDER BY createdDate desc")
fun listAll(): Flow<List<RecordEntity>>
答案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.
- a fourth way, using CTE's, can be found at https://stackoverflow.com/questions/76278049/how-can-i-add-the-sencond-sort-item-when-i-use-case-to-require-parameter-for-sql/76285491#76285491
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("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()
}
/* handle neither orderColumn????? */
return selectOption1() /* e.g. default */
}
Option 2. using @RawQuery
Have something along the lines of:-
@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"))) }
}
- 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(
"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>>
All the above have been tested (compiled and run), but on the main thread and hence no suspend or equivalent.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论