mysql中locate('sub', field)与instr(field, 'sub')参数顺序相反,写反则返回0;sql server用charindex,postgresql用position或strpos;find_in_set仅适用于set类型字段。

MySQL 用 LOCATE 还是 INSTR?参数顺序别写反
MySQL 里最常用的是 LOCATE 和 INSTR,但它们参数顺序相反,写错就永远查不到结果。
-
LOCATE('sub', field):第一个是子串,第二个是字段,返回位置(从 1 开始)或 0 -
INSTR(field, 'sub'):第一个是字段,第二个是子串,行为和LOCATE一致但顺序相反 - 写成
LOCATE(field, 'sub')或INSTR('sub', field)都会返回 0 —— 因为 MySQL 把它当成“在短字符串里找长字符串” - 任一参数为
NULL,整个表达式结果就是NULL,在WHERE中这行会被跳过(不是FALSE)
SQL Server 必须用 CHARINDEX,LIKE 有隐含性能代价
CHARINDEX('abc', field) > 0 是 SQL Server 最直接、可走索引(部分场景)的写法;LIKE '%abc%' 虽通用,但无法利用普通 B-tree 索引。
-
CHARINDEX返回 1-based 位置,找不到时返回 0,语义清晰 -
LIKE '%abc%'在字段开头或结尾带通配符时,基本等于全表扫描 - 如果字段上有全文索引,且查询复杂,可考虑
CONTAINS,但配置成本高,不推荐简单包含判断 - 注意大小写:默认按数据库排序规则(collation),若需忽略大小写,统一转小写:
CHARINDEX(LOWER('ABC'), LOWER(field)) > 0
PostgreSQL 别用 LOCATE,它根本不存在
PostgreSQL 不支持 LOCATE 或 INSTR,直接执行会报错:ERROR: function locate(unknown, unknown) does not exist。
- 必须用标准 SQL 的
POSITION('sub' IN field),注意IN关键字不能省略 - 或者用兼容 Oracle 风格的
STRPOS(field, 'sub'),参数顺序和 MySQL 的INSTR一致 - 两者都返回 1-based 位置或 0,可用于
WHERE条件直接比较 - 大小写敏感同理,需配合
LOWER()使用:POSITION(LOWER('Error') IN LOWER(field)) > 0
FIND_IN_SET 只适用于逗号分隔的 SET 字段,别乱套用
看到函数名带 “FIND” 和 “SET”,容易误以为它能查任意文本字段。实际上它只对定义为 SET 类型的字段有效,比如 status SET('active','error','pending')。
- 对普通
VARCHAR或TEXT字段(如日志内容)用FIND_IN_SET('error', message),结果恒为 0 或NULL,且毫无提示 - 字段值必须严格是
'active,error'这种无空格、纯逗号分隔格式,多一个空格就失效 - 性能比
LIKE还差,完全无法走索引,纯字符串遍历 - 真正该用它的场景极少,绝大多数“包含”需求应避开它
FIND_IN_SET 查普通文本字段。











