是否可以在普通的sql Slick中使用IN子句来表示整数?

Roy*_*Lin 7 scala slick

这里有一个类似的问题,但实际上并没有回答这个问题.

是否可以在普通的sql Slick中使用IN子句?

请注意,这实际上是更大,更复杂的查询的一部分,所以我需要使用普通的sql而不是光滑的提升嵌入.像下面这样的东西会很好:

val ids = List(2,4,9)
sql"SELECT * FROM coffee WHERE id IN ($ids)"
Run Code Online (Sandbox Code Playgroud)

Ben*_*ich 13

sql前缀解锁StringContext,您可以设置SQL参数.列表没有SQL参数,因此如果您不小心,可以轻松地在此处打开自己的SQL注入.有一些很好的(和一些危险的)关于处理这个问题的SQLServer上建议这个问题.你有几个选择:

你最好的选择可能是使用#$运算符mkString来插入动态SQL:

val sql = sql"""SELECT * FROM coffee WHERE id IN (#${ids.mkString(",")})"""
Run Code Online (Sandbox Code Playgroud)

这没有正确使用参数,因此可能对SQL注入和其他问题持开放态度.

另一种选择是使用常规字符串插值并mkString构建语句:

val query = s"""SELECT * FROM coffee WHERE id IN (${ids.mkString(",")})"""
StaticQuery.queryNA[Coffee](query)
Run Code Online (Sandbox Code Playgroud)

这与使用方法基本相同#$,但在一般情况下可能更灵活.

如果SQL注入漏洞是一个主要问题(例如,如果ids用户提供的元素),您可以使用参数为每个元素构建一个查询ids.然后,您需要提供一个自定义SetParameter实例,以便光滑可以转换List为参数:

implicit val setStringListParameter = new SetParameter[List[String]]{
    def apply(v1: List[String], v2: PositionedParameters): Unit = {
        v1.foreach(v2.setString)
    }
}

val idsInClause = List.fill(ids.length)("?").mkString("(", ",", ")")
val query = s"""SELECT * FROM coffee WHERE id IN ($idsInClause)"""
Q.query[List[String], String](query).apply(ids).list(s)
Run Code Online (Sandbox Code Playgroud)

既然你idsInts,这可能不是一个问题,但如果你更喜欢这种方法,你只需要改变setStringListParameter使用Int而不是String:

  • 如果`ids`有类型`List [Int]`我就看不到sql注入是如何可能的,即使它们是用户提供的. (3认同)
  • @Daenyth这绝对不是一个问题(虽然有时整数SQL注入可能是一个问题,因为除以零或其他异常,然后利用失败的状态 - 谷歌"SQL注入整数").但是我会说最好的做法是使用参数来避免出现问题(例如,如果另一个开发人员将类型更改为`String`以适应包含某些字符的新类型ID,那该怎么办).我真的只是在这里用"字符串"来覆盖案例. (2认同)

小智 7

  val ids = List(610113193610210035L, 220702198208189710L)

  implicit object SetListLong extends SetParameter[List[Long]] {
    def apply(vList: List[Long], pp: PositionedParameters) {
      vList.foreach(pp.setLong)
    }
  }

  val select = sql"""
        select idnum from idnum_0
        where idnum in ($ids#${",?" * (ids.size - 1)})
    """.as[Long]
Run Code Online (Sandbox Code Playgroud)

@本·赖希是对的。这是另一个示例代码,在slick 3.1.0上进行测试。

($ids#${",?" * (ids.size - 1)})