应使用ESCAPE子句显式指定转义符(如!、$),避免依赖反斜杠;转义符须为字符串字面量且不能是_、%或待匹配字符;用户输入需预先转义,ORM和参数化查询中ESCAPE不可参数化。
LIKE 查询里下划线 _ 和百分号 % 被当成通配符了怎么办
直接用 like 查含 _ 或 % 的字符串,比如查用户名 user_name,结果会把 useraname、user1name 全捞出来——因为 _ 匹配任意单字符。% 更危险,可能扫出完全不相关的记录。
必须显式声明转义字符,不能依赖默认行为。不同数据库对 ESCAPE 的支持和默认转义符不一致,硬编码 很容易在 PostgreSQL 里报错,在 SQL Server 里又没效果。
- 用
ESCAPE子句明确定义转义符,例如LIKE 'user_name' ESCAPE '' - 转义符本身不能是
_、%或你打算匹配的其他特殊字符(比如选!就比更少冲突) - MySQL 5.7+ 默认允许
,但需确认sql_mode没开NO_BACKSLASH_ESCAPES;PostgreSQL 完全不认做默认转义,必须写ESCAPE - 如果字段值来自用户输入,先对原始字符串做一次转义(比如把
_替成_),再拼进 SQL,别靠前端“记得加反斜杠”
PostgreSQL 里写 ESCAPE '\' 还报错?
不是语法错,是字符串字面量解析阶段就翻车了。PostgreSQL 把两个反斜杠 \ 当作一个字面量 ,再传给 ESCAPE 时,实际生效的还是单个 ——但它不支持 当转义符,所以报 ERROR: invalid escape string。
解决办法是换一个数据库认可且不会被字符串引擎提前吃掉的字符,比如 ! 或 $:
-
WHERE name LIKE 'user!_name' ESCAPE '!'—— 这里!是转义符,!_表示字面量下划线 - 避免用
,除非你明确知道连接层(如 pg driver)没做二次转义 - 如果用 ORM(如 SQLAlchemy),检查它是否自动包裹
ESCAPE;Django 的__contains不走LIKE,但__regex或原生查询仍要自己处理
Oracle 和 SQL Server 的 ESCAPE 写法有啥坑
Oracle 允许省略 ESCAPE 并用反斜杠转义,比如 LIKE 'user_name',但这只是 Oracle 的扩展行为,跨库迁移时直接失效。SQL Server 更麻烦:它默认不支持 ESCAPE 关键字,得用方括号或 CHARINDEX + SUBSTRING 绕开。
- Oracle 推荐统一写
ESCAPE显式声明,别依赖隐式反斜杠(尤其当ESCAPE字符本身是时,要写成ESCAPE '\') - SQL Server 2012+ 支持
ESCAPE,但必须确保兼容级别 ≥ 110;老版本只能用CHARINDEX('%', col) > 0配合字符串拆解,性能差很多 - 所有数据库里,转义符不能出现在被匹配的模式末尾(如
'abc%'后面没字符可逃),否则语法错误
用参数化查询时,ESCAPE 字符还能动态传入吗
不能。SQL 标准规定 ESCAPE 后必须是字符串字面量,不是表达式或参数占位符。写成 LIKE ? ESCAPE ? 在绝大多数驱动里会报语法错误,比如 psycopg2 直接抛 ProgrammingError,MySQL Connector/Python 也拒绝执行。
- 转义符必须硬编码在 SQL 字符串里,比如
... LIKE ? ESCAPE '$' - 如果业务需要支持多种转义符(比如配置化),只能动态拼 SQL 字符串——但务必对转义符本身做白名单校验(只允许
!、$、#等无害字符) - 参数只负责传入被搜索的模式值,且该值内部已按约定转义好(例如用户搜
100%,后端应生成'100$%'再塞进参数)
ESCAPE 就万事大吉,结果转义符本身被数据库或驱动提前解析了一轮——多一层字符串处理,就多一个吃掉反斜杠的地方。










