any本质是存在性比较,只支持=、>等标量运算符,不支持like模糊匹配;postgresql例外支持expr like any(array),但需子查询转array,mysql等主流数据库直接报错。

ANY 运算符本质是“存在性比较”,不是模糊匹配工具
直接用 ANY 做模糊匹配(比如想实现类似 LIKE 的通配效果)会失败——ANY 只接受标量比较(=、>、 等),不支持 <code>LIKE 或正则。它真正的作用是:把左侧表达式和子查询返回的**每一行结果逐个比较**,只要有一个满足条件就返回 TRUE。
常见错误现象:WHERE name LIKE ANY (SELECT pattern FROM patterns) —— 大多数数据库(PostgreSQL 除外)会报错,因为 LIKE 不能直接和 ANY 组合。
- PostgreSQL 是个例外:支持
expr LIKE ANY (array),但注意它要求右边是数组,不是子查询;若用子查询,得先ARRAY(SELECT ...) - MySQL / SQL Server / Oracle 不支持
LIKE ANY语法,强行写会直接报错ERROR 1064或类似解析错误 - 真正可移植的做法是把模糊逻辑放进子查询内部,让子查询返回布尔结果,再用
EXISTS或IN衔接
用 EXISTS + 子查询替代 ANY 实现“多模式模糊匹配”
当你要检查某字段是否匹配多个模糊模式(例如:用户名包含 “admin”、“test” 或 “dev” 中任意一个),EXISTS 比 ANY 更直接、更兼容。
示例场景:查出所有用户名中包含黑名单关键词的用户
SELECT * FROM users u WHERE EXISTS ( SELECT 1 FROM blacklist b WHERE u.username LIKE '%' || b.keyword || '%' );
-
EXISTS自动处理空子查询结果(返回FALSE),而ANY在子查询为空时返回UNKNOWN,可能影响WHERE判定 - 如果
blacklist.keyword有NULL值,LIKE比较会变成UNKNOWN,建议加WHERE b.keyword IS NOT NULL - 性能上:给
blacklist.keyword加索引没用(LIKE左侧通配导致无法走 B-tree 索引),但可以考虑全文索引或pg_trgm(PostgreSQL)加速
PostgreSQL 中用 ARRAY + LIKE ANY 的正确写法
仅限 PostgreSQL,且必须把子查询转成数组。直接 LIKE ANY (SELECT ...) 语法非法。
正确写法:
SELECT * FROM users WHERE username LIKE ANY ( ARRAY(SELECT '%' || keyword || '%' FROM blacklist WHERE keyword IS NOT NULL) );
-
ARRAY(SELECT ...)是关键包装,否则报错operator does not exist: text ~ any (record) - 若子查询返回零行,
ARRAY()返回空数组,LIKE ANY (ARRAY[]::text[])结果为FALSE,行为可预期 - 注意字符串拼接方式:
||是 PostgreSQL 默认连接符;MySQL 要用CONCAT(),SQL Server 用+,跨库时别硬搬
为什么不用 IN + 子查询做模糊匹配?
IN 只能做精确匹配,写成 username IN (SELECT keyword FROM blacklist) 是完全不同的语义——它查的是用户名是否“等于”某个关键词,而非“包含”。
- 想用
IN达到模糊效果?不可能。子查询里加LIKE也不行,因为IN左右两边都必须是标量值 - 有人误写
username LIKE IN (SELECT ...),这语法直接被拒绝,错误信息通常是syntax error at or near "IN" - 真正要复用子查询结果做多条件模糊,唯一稳健路径是把模糊判断下推到子查询里,用
EXISTS包裹
复杂点在于:模糊匹配本身就不适合集合运算,ANY 的设计初衷是数值/等值比较。强行套用反而绕远路,还牺牲可读性和兼容性。实际项目里,先明确需求到底要“是否存在匹配”还是“匹配了哪一个”,再选 EXISTS 或带 JOIN 的显式关联。











