房间 - 选择带有 IN 条件的查询?

Posted

技术标签:

【中文标题】房间 - 选择带有 IN 条件的查询?【英文标题】:Room - Select query with IN condition? 【发布时间】:2018-07-02 12:56:11 【问题描述】:

是否可以在 Room 中使用 SQLite 的 IN 条件?

我正在尝试从我的数据库中选择一个项目列表,其中某个列的值(在本例中为 TEXT 列)与一组过滤器值中的任何一个匹配。据我所知,这在 SQL 和 SQLite 中很容易完成,只需在 SELECT 语句 (see here) 中添加 IN 条件即可。但是,我似乎无法让它与 Room 一起使用。

我不断收到此错误:

Error:(70, 25) error: no viable alternative at input 'SELECT * FROM Table WHERE column IN :filterValues'

(其中DAO @Query-annotated 方法的输入称为filterValues

我现在尝试了三种不同的方法:

    将参数作为List<String> 传递 将参数作为String[] 传递 最后将参数传递为简单的String,但格式为(value_1, value_2, ..., value_n)

最后一个应该很容易工作,因为它将(或至少应该)直接转换为SELECT * FROM Table WHERE column IN (value_1, value_2, ..., value_n),如果您只是访问直接数据库。

【问题讨论】:

***.com/a/48370198/115145 @CommonsWare 是的,这会立即解决我的问题。不幸的是,我在所有搜索中都没有遇到过这个问题,因为我专门寻找有关 Room 和 SELECT 的信息,并带有 IN 条件(该问题中实际上没有提到)。 请注意,the question 中提到了所有这些内容。 【参考方案1】:

所以当我准备提交这个问题时,我仔细检查了一堆我之前查过的东西,发现我不知何故错过了一些东西,并且可以避免这个问题的必要性。

事实证明,这两个选项:

    将参数作为List<String> 传递 将参数作为String[] 传递

是可行的(并且您可以将String 替换为数据库可以表示的任何类型,例如charint),您只需从以下位置更改@Query 注释中的语法:

@Query("SELECT * FROM Table WHERE column IN :filterValues")

到这里:

@Query("SELECT * FROM Table WHERE column IN (:filterValues)")

很容易,对吧?

请注意,Room 似乎不支持上面的第三种方法(将参数简单地传递为String,但格式化为(value_1, value_2, ..., value_n)),但这可能不是一件坏事,因为这是一种艰难的方式。

由于我已经输入了整个内容,我想我会留下这个问题,以防其他人像我一样难以找到这个解决方案并偶然发现这个问题。

【讨论】:

有什么方法可以让它与自定义类一起工作?例如。枚举。它似乎没有使用 TypeConverter 来转换自定义类的列表。 不确定我是否完全理解 - 您想搜索自定义对象的集合/列表吗?自定义对象/类可以在带有@TypeConverters 的 Room 中使用,但这用于将整个表格(或该表格列的子集)转换为一个类(反之亦然)。 SQL 查询搜索/索引各个列,这些列仍必须是 SQL 支持的数据类型(String、Int 等)。除了传递自定义对象列表之外,您可以做的是让多个参数对应于这些对象中的某些字段,每个参数映射到单个列。 例如@Query("SELECT * FROM agenda WHERE day IN (:days)") fun getAgenda(days: List<DayOfWeek>) 其中enum class DayOfWeek MON, TUES, ... TypeConverter 可用于在所有其他上下文中查询/获取 DayOfWeek,除了(似乎)IN 我猜问题是TypeConverter 不知道如何解析列表。尝试制作一个接受 List 并吐出 List 的转换器(我假设它是一个 int 或字符串)。或者,只需自己构建该列表并将其作为参数发送。 看起来这可能已在 2.1.0-alpha07 中修复 :) issuetracker.google.com/issues/122066791【参考方案2】:

您好,您可以使用以下查询:

 @Query("SELECT * FROM user WHERE uid IN(:userIds)")
 public abstract List findByIds(int[] userIds);

 @Query("SELECT * FROM user WHERE uid IN(:userIds)")
 public abstract List findByIds(List<Integer> userIds);

【讨论】:

对我有用。非常感谢!【参考方案3】:

Kotlin 中的上述答案类似,您可以使用vararg 而不是arraylist

@Query("SELECT * FROM user WHERE uid IN (:userIds)")
fun getUsers(vararg userIds: Int): List<User>?

并像repository.getUsers(1, 2, 3) 一样使用它。

如果需要,将vararg 转换为list 请参阅https://proandroiddev.com/kotlins-vararg-and-spread-operator-4200c07d65e1(使用*format(output, *params))。

【讨论】:

以上是关于房间 - 选择带有 IN 条件的查询?的主要内容,如果未能解决你的问题,请参考以下文章

选择带有日期条件的查询

带有 where 条件的 PL/SQL 更新查询作为带有一些空值的选择查询

遇到需要满足多个条件的 MySQL Join 问题

SQL:如何在带有“NOT IN”条件的“Where”子句中使用“and”和“or”

MYSQL 查询 WHERE IN 条件的问题

使用 IN 条件选择行并分组