preparedstatement 不转义 like 中的 % 和 _,需在 sql 中用 escape 显式声明转义符,如 "like ? escape ''" 并传入 "ab%"; 转义仅用于字面匹配,非防注入。

在使用 Java PreparedStatement 查询数据库时,百分号(%)和下划线(_)本身是 SQL LIKE 子句中的通配符,不是 PreparedStatement 的“特殊字符”——PreparedStatement 本身不会对它们做任何特殊处理,也不会自动转义。真正需要转义的场景,是当你想让它们作为**普通字符参与模糊匹配**(比如查真实包含 % 的字符串),这时必须在 SQL 层显式声明转义规则。
LIKE 中的 % 和 _ 需要 SQL 层转义,不是 PreparedStatement 责任
PreparedStatement 的核心作用是参数化占位符(?)并防止 SQL 注入,它不解析、不修改 SQL 字符串中的字面量内容(包括 LIKE 模式里的 % 和 _)。所以转义必须由你写在 SQL 语句中,并配合 ESCAPE 子句使用。
- 把想当作普通字符的
%或_替换成「转义字符 + 该字符」,例如用%、_ - 在 SQL 中明确指定转义字符,如
LIKE ? ESCAPE '' - 参数值里直接传入含转义符的字符串(如
"ab%cd"),PreparedStatement 会原样送入数据库执行
正确写法示例(以反斜杠 为转义符)
假设查字段值中**真实包含百分号**的记录:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
String sql = "SELECT * FROM product WHERE name LIKE ? ESCAPE '\'"; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, "discount\%"); // 匹配 "discount%" 这个字面值 ResultSet rs = ps.executeQuery();
注意:Java 字符串中 \ 表示一个反斜杠字符,SQL 中最终生效的是 %,再配合 ESCAPE '' ,数据库就知道 % 不是通配符而是字面百分号。
其他常用转义方案与注意事项
- 可选任意 ASCII 字符作转义符(如
!、~),只要在ESCAPE和参数中保持一致,例如LIKE ? ESCAPE '!'→ 参数传"ab!%cd" - 若模式中需匹配转义符本身(如查字符串
"abcd"),需写成双份:"ab\\cd"(Java 字符串中四个反斜杠 → SQL 中两个 → 数据库识别为一个字面反斜杠) - 不同数据库对 ESCAPE 字符支持略有差异(如 MySQL 默认支持
,Oracle 要求显式声明),建议统一用标准 SQL 的ESCAPE写法 - 如果只是精确匹配(不用 LIKE),完全不需要转义 —— 直接用
= ?,PreparedStatement 自动安全处理所有字符
不要混淆:这不是防 SQL 注入,而是控制 LIKE 语义
有人误以为对 % 做字符串替换(如 input.replace("%", "\%"))就能“解决注入”,这是错的。PreparedStatement 已经确保参数不参与 SQL 解析,根本不存在注入风险;你手动替换反而可能破坏业务逻辑(比如用户真想搜通配符功能)。是否转义,只取决于你的查询意图:要模糊匹配效果,就保留 %;要字面匹配,才加 ESCAPE。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










