MySQL中LIKE查询携带比较运算符时查询失效问题求助
问题排查思路
- 先定位异常到底出在哪个链路节点,别上来就把问题算在LIKE语法头上。要分清异常是应用层SQL拦截、中间件规则阻断、还是数据库实际执行时报错:很多自研SQL代理、业务框架的SQL注入校验、WAF规则,会直接把字符串里带的<、>特征字符判定为恶意SQL注入攻击,直接拦下来,根本不会把SQL下发到数据库。
- 逐环节核对SQL文本是否一致。对比代码层拼完的SQL、中间件转发的SQL、数据库实际收到并执行的SQL三者的文本差异,重点查你示例SQL里出现的
<>转义实体:这组字符是HTML转义后的<、>,如果没经过反转义就直接拼进SQL,实际数据库收到的LIKE匹配串根本不是你要的带<>的文本,而是字面量的转义实体字符串,既查不到目标数据,还可能因为字符串结构不对触发解析错误。 - 排除数据库侧的解析兼容问题。主流关系型数据库的LIKE操作符里,<、>都是没有特殊语义的普通字符,正常执行根本不需要额外转义。如果确认SQL已经成功发到数据库还报错,就要查数据库的SQL解析模式,是不是有自定义规则把LIKE字符串里的<、>当成了比较运算符,错把原来的单条WHERE条件拆成多段,导致语法结构错乱。
可落地的解决方案
- 打通全链路日志,把各个环节的SQL都打出来核对。对比应用层拼完的最终SQL、中间件转发的SQL、数据库执行的SQL的差异,定位到底是哪一步把字符改了、或者拦了。如果是安全规则的误拦截,就把这类业务合法的特殊字符请求加进白名单,别把业务字段存的正常特殊字符和SQL语法层的比较运算符混为一谈做拦截。
- 优先用预编译参数绑定的方式写LIKE查询,别直接把业务字符串硬拼到SQL文本里。示例写法:
SELECT * FROM tms_customers WHERE tms_customers.NAME LIKE CONCAT('%', ?, '%^|!@%')
把带<、>的匹配值当预编译参数传进去,既不会被框架的字符串转义逻辑改了原始匹配值,也不会触发SQL注入校验的误判,从根上解决特殊字符被篡改、被拦截的问题。注意预编译场景下别提前转义匹配值里的特殊字符,保证原始值完整透传到数据库就行。 - 针对必须直接拼SQL文本的场景,显式声明LIKE的转义规则。如果数据库确实有特殊字符解析兼容问题,可以通过
ESCAPE子句明确指定转义符,让数据库把LIKE字符串里的<、>识别为普通文本字符,别让解析器把这些字符当成语法运算符拆条件结构。
内容的提问来源于stack exchange,提问作者Ali Hammad
相关产品推荐
相关产品推荐

