MySQL里的双竖线||是一个比较特殊的运算符,它的行为不是固定的,而是取决于sql_mode的设置。在默认模式下,||等价于逻辑OR;而开启PIPES_AS_CONCAT之后,||变成了字符串拼接运算符,作用类似CONCAT函数。更关键的是,这两种身份对应的优先级完全不同,同一个表达式在不同模式下求值顺序可能大相径庭,直接影响到查询结果的正确性。

PIPES_AS_CONCAT模式是什么,它如何改变||的行为
PIPES_AS_CONCAT是MySQL的一个sql_mode选项,设计初衷是为了兼容标准SQL以及Oracle、PostgreSQL等数据库的语法习惯。在这些数据库中,||一直是字符串拼接的标准运算符,比如'hello' || ' world'会得到hello world。MySQL为了迁移方便,提供了这个开关。
在默认模式下执行SELECT 'a' || 'b',MySQL把||当作逻辑OR来处理,两个非空字符串都被当作真值,结果会是整数1。而开启模式后,同样的语句返回字符串ab。可以用下面的语句开启并测试:
SET sql_mode = 'PIPES_AS_CONCAT'; SELECT 'a' || 'b'; -- 返回字符串 'ab' SELECT 'Hello' || ' ' || 'World'; -- 返回 'Hello World' -- 对比默认模式 SET sql_mode = ''; SELECT 'a' || 'b'; -- 返回整数 1,逻辑OR的结果
需要注意的是,PIPES_AS_CONCAT改变的不只是运算含义,还有它在整个运算符优先级体系中的位置,这一点往往被忽视,却最容易引发线上问题。
两种身份下的优先级差异详解
当||作为逻辑OR时,它的优先级非常低。MySQL中逻辑OR的优先级低于逻辑AND(&&或AND),而逻辑AND又低于所有比较运算符和算术运算符。也就是说,在默认模式下,表达式里只要有别的运算符,||几乎总是最后才被求值。
而开启PIPES_AS_CONCAT后,||的优先级会跳到很高的位置——高于乘法运算符*和除法运算符/,仅次于一元运算符(如负号)。这个设定是有意为之的:拼接运算符优先级高,意味着a || b * c会先算出b*c再参与拼接之前的运算顺序判断,更贴近标准SQL的行为。用一个例子直观感受一下:
-- 默认模式:|| 是逻辑OR,优先级低 SET sql_mode = ''; SELECT 2 || 3 + 5; -- 3+5先算得8,2和8都为真,逻辑OR结果为 1 -- 开启PIPES_AS_CONCAT:|| 是拼接,优先级高于 + SET sql_mode = 'PIPES_AS_CONCAT'; SELECT 'a' || 'b' + 'c'; -- || 优先级高,先拼接 'a'||'b' 得 'ab' -- 再进行数值加法,'ab'和'c'转数字都是0,结果为 0
可以看到,同一个表达式|| 'b' +的组合在不同模式下求值路径完全不同。如果不显式加括号控制顺序,代码的可读性和可移植性都会很差。
实际开发中的注意事项与最佳实践
第一,要警惕模式的会话级差异。sql_mode可以在全局、会话两个级别设置,如果开发环境开启了PIPES_AS_CONCAT而生产环境没有,同一段SQL可能产生不同结果。建议把sql_mode明确写入应用连接配置或部署脚本中,而不是依赖服务器默认值。
第二,即使开启了PIPES_AS_CONCAT,也不建议在复杂表达式中裸写||。显式使用CONCAT函数或添加括号,能让意图更清晰:
-- 不推荐:依赖优先级 SELECT first_name || ' ' || last_name * 1 FROM users; -- 推荐:显式函数调用,行为与模式无关 SELECT CONCAT(first_name, ' ', last_name) FROM users;
第三,注意数据库之间的差异。MariaDB从10.3版本起可以直接将||作为拼接运算符(通过sql_mode或默认行为支持),PostgreSQL中||始终是拼接且不允许操作数为NULL(NULL会导致结果为NULL),Oracle则把NULL当空串处理。跨库迁移时,CONCAT及CONCAT_WS是最稳妥的选择,其中CONCAT在MySQL中还会忽略NULL参数,这一点又和标准SQL不同。
总结一下:||在MySQL中的优先级完全由PIPES_AS_CONCAT模式决定,作为逻辑OR时优先级很低,作为拼接运算符时优先级高于乘除法。理解这个差异,显式管理sql_mode,并在关键逻辑中使用CONCAT函数替代,是避免隐式行为陷阱的三个有效手段。
PIPES_AS_CONCATMySQL sql_mode运算符优先级修改时间:2026-09-06 04:24:26