【问题标题】:Is it possible to use IN clause in plain sql Slick?是否可以在普通 sql Slick 中使用 IN 子句?
【发布时间】:2013-06-28 19:24:32
【问题描述】:

例如,我想创建以下查询:

SELECT c.* FROM Coffees c WHERE c.name IN ('robusta', 'arabica')

我的尝试失败了:

val cnames = List("robusta", "arabica")
sql""" SELECT c.* FROM Coffees c WHERE c.name IN ${cnames} """
  could not find implicit value for parameter pconv: 
  scala.slick.jdbc.SetParameter[List[String]]

是否可以在 Slick 普通 sql 查询中以某种方式使用 in 子句?

【问题讨论】:

  • 最让我困惑的是,在 Slick 的提升嵌入中,这几乎是一项不费吹灰之力的任务。
  • 我使用slick-pgselect * from Coffees where array_position(${cnames}, name) is not null
  • 对于较新版本的 Slick,这里也有回答:stackoverflow.com/questions/31156613/…

标签: scala scala-2.10 slick


【解决方案1】:

类型安全的“提升嵌入”API 也支持这一点:

val ids = List(1,2,3)
val q = for {
  f <- Foo if f.id inSet ids // ids is not bound
}

slick.typesafe.com/doc/1.0.1/api/index.html#scala.slick.lifted.ColumnExtensionMethods

【讨论】:

  • 谢谢!我也可以在 Slick 3.0 中使用它:query.filter(_.id inSet ids)
  • 这如何应用于普通的 SQL Slick(正如问题所问的那样)?我正在寻找那个答案,但这并不适用。
  • 不适用。如果你使用ids,你会得到Could not find implicit value for parameter e: slick.jdbc.SetParameter[List[String]]。投反对票,因为尽管它在其他情况下有效,但它不能回答这个问题。相关问题:github.com/slick/slick/issues/1335
【解决方案2】:

虽然SQL注入不安全,但可以使用#$插值器:

val ids = idList.mkString("'", "','", "'")
val q = sql"""select name from mytable where id in (#$ids)"""

【讨论】:

    【解决方案3】:

    我没有看到任何开箱即用的东西来处理这个问题。你最好的选择可能是这样的:

    val cnames = List("robusta", "arabica").mkString("'", "','", "'")
    val query = sql""" SELECT c.* FROM Coffees c WHERE c.name IN (${cnames}) """
    

    【讨论】:

    • @Rogarch,因为事情已经发生了变化,我的答案不再正确,您能否将接受的答案更改为下面的答案,以便我可以删除此答案?
    • 如果插值使用#$而不是$,这将起作用,但它仍然非常不安全。 :) slick.typesafe.com/doc/2.1.0/sql.html scala&gt; sqlu""" update tbl_foo set x = 1 where y in #$z """ res30: scala.slick.jdbc.StaticQuery[Unit,Int] = &lt;function1&gt; scala&gt; res30.getStatement res31: String = " update tbl_foo set x = 1 where y in (1,2) " (对不起,当我无法插入返回时,我不知道如何很好地格式化它)
    • 对slick不太熟悉,但这不会引入SQLi漏洞吗?还是由sql quasiquote 处理?
    【解决方案4】:

    有一个库(除其他外)将列表属性的绑定器引入到 Slick 的 SQL 插值器: https://index.scala-lang.org/tarao/slick-jdbc-extension-scala/slick-jdbc-extension

    页面示例代码:

      import util.NonEmpty
    
      def findAll(entryIds: Option[NonEmpty[Long]]): Seq[Entry] = entryIds match {
        case Some(ids) => run { sql"""
        | SELECT * FROM ${table}
        | WHERE entry_id IN $ids
        """.as[Entry] }
        case None => Seq.empty
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-05
      • 2019-03-03
      • 1970-01-01
      相关资源
      最近更新 更多