You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Slick中编写带%通配符LIKE的原生SQL查询参数越界问题

问题原因

Slick的sql原生SQL插值器会按照SQL语法规则解析插值位置:

  • 只有不在SQL字符串字面量(单引号包裹的内容)内部的$开头变量,才会被识别为待绑定的预编译参数,替换为JDBC的?占位符后按顺序传值
  • 单引号内部的$标记不会被插值器识别,会直接作为普通SQL字符串内容处理,最终会导致插值器统计的参数数量和JDBC驱动识别到的占位符数量不匹配,抛出parameter index out of range异常

硬编码搜索值可以正常运行,是因为此时SQL中不存在任何插值变量,属于完全静态的SQL语句,不会触发参数绑定逻辑,自然不会报错。

注意:手动给插值变量加单引号是错误写法,Slick做预编译参数绑定时,会自动根据参数类型处理引号包裹、特殊字符转义逻辑,不需要手动加单引号。

安全正确的实现方式

将%通配符和搜索内容的拼接逻辑放在Scala代码侧完成,把拼接好的完整LIKE匹配模式作为独立的插值参数传入即可,这种写法走JDBC预编译参数绑定,完全没有SQL注入风险。

val someText: String = "some text"
// 在业务代码侧拼接LIKE匹配通配符
val searchPattern = s"%$someText%"
val query = sql"""SELECT mt.id, mt.name FROM my_table mt
        WHERE mt.name LIKE $searchPattern;""".as[MyEntity]
val queryResult: Future[Vector[MyEntity]] = db.run(query)

如果需要避免用户输入内容中自带的%、_这类LIKE通配符干扰匹配结果,可以先对输入内容做转义处理:

val someText: String = "some text"
// 转义LIKE语法中的特殊字符
val escapedText = someText
  .replace("\\", "\\\\")
  .replace("%", "\\%")
  .replace("_", "\\_")
val searchPattern = s"%$escapedText%"
val query = sql"""SELECT mt.id, mt.name FROM my_table mt
        WHERE mt.name LIKE $searchPattern ESCAPE '\';""".as[MyEntity]
val queryResult: Future[Vector[MyEntity]] = db.run(query)

内容的提问来源于stack exchange,提问作者rapt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 06:18:22