sql 前缀解锁 StringContext,您可以在其中设置 SQL 参数。列表没有 SQL 参数,因此如果您不小心,很容易在此处打开自己的 SQL 注入。关于this question 上的 SQLServer 处理此问题有一些好的(也有一些危险的)建议。您有几个选择:
您最好的选择可能是使用#$ 运算符和mkString 来插入动态SQL:
val sql = sql"""SELECT * FROM coffee WHERE id IN (#${ids.mkString(",")})"""
这不能正确使用参数,因此可能会导致 SQL 注入和其他问题。
另一种选择是使用常规字符串插值和mkString 来构建语句:
val query = s"""SELECT * FROM coffee WHERE id IN (${ids.mkString(",")})"""
StaticQuery.queryNA[Coffee](query)
这与使用#$ 的方法基本相同,但在一般情况下可能更灵活。
如果 SQL 注入漏洞是一个主要问题(例如,如果ids 的元素是用户提供的),您可以为ids 的每个元素构建一个带有参数的查询。然后你需要提供一个自定义的 SetParameter 实例,以便 slick 可以将 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)
由于您的ids 是Ints,这可能不太需要担心,但如果您更喜欢这种方法,您只需将setStringListParameter 更改为使用Int 而不是String: