mysql中concat遇null即返回null,需用ifnull或coalesce兜底;concat_ws可跳过null但保留分隔符;跨库应选||(pg)、isnull+(sql server)或嵌套concat(oracle);避免在where/order by中使用以保索引;字符集须统一为utf8mb4。

MySQL里用CONCAT拼接字段,空值会让整条结果变NULL
这是最常踩的坑:只要CONCAT任意一个参数是NULL,整个返回值就是NULL,不是空字符串。比如CONCAT(first_name, ' ', last_name),如果first_name为NULL,哪怕last_name有值,结果也是NULL。
实际做法是提前把可能为空的字段转成空字符串:
- 用
IFNULL(col, '')或COALESCE(col, '')兜底 - MySQL 8.0+ 可直接用
CONCAT_WS(' ', col1, col2),它自动跳过NULL(但注意分隔符仍会保留,不会多加) - 别依赖
CONCAT自动类型转换——数字字段拼接时,NULL依然生效,不因上下文变成'0'
PostgreSQL和SQL Server不用CONCAT,得换写法
不同数据库对CONCAT支持差异大:PostgreSQL 9.1+ 才有CONCAT,且行为和MySQL不完全一致;SQL Server 2012+ 支持,但老版本只能用+运算符——而+遇到NULL同样返回NULL。
跨库兼容性更强的做法:
- PostgreSQL:优先用
||操作符,如col1 || ' ' || col2,它对NULL更宽容(NULL || 'x'→'x') - SQL Server:用
ISNULL(col, '')配合+,或升级到2012+后用CONCAT(col1, ' ', col2)(这个版本的CONCAT会自动把NULL转为空字符串) - Oracle:没有
CONCAT多参数版,只能嵌套用CONCAT(CONCAT(a,b),c),或直接用||
CONCAT性能不高,大数据量拼接别放WHERE或ORDER BY里
在WHERE条件中写CONCAT(first_name, last_name) LIKE '%john%',会导致索引失效;在ORDER BY里用CONCAT也会让排序无法利用索引,全表扫描风险高。
真要按拼接结果筛选或排序,优先考虑:
- 建生成列(MySQL 5.7+ / PostgreSQL 12+):
ALTER TABLE users ADD full_name VARCHAR(100) GENERATED ALWAYS AS (CONCAT(first_name, ' ', last_name)) STORED,再给full_name加索引 - 应用层拼接:查出原始字段,在代码里组合,避免数据库层复杂计算
- 确认是否真需要拼接——有时用
first_name LIKE ? OR last_name LIKE ?语义更准、性能更好
中文字符、emoji和编码问题会让CONCAT输出乱码
如果字段是utf8mb4,但连接或客户端设置是utf8(MySQL旧版默认),CONCAT结果可能出现问号或截断,尤其是含emoji或生僻汉字时。
检查和修复要点:
- 确认字段、表、连接三者字符集都是
utf8mb4,不能只改表 - MySQL客户端连接时加上
?charset=utf8mb4(如JDBC URL末尾) - 用
SHOW VARIABLES LIKE 'character_set%'核对character_set_client、character_set_connection、character_set_results是否一致 - 别依赖
CONVERT(... USING utf8mb4)临时转换——治标不治本,源头统一才可靠
拼接本身不改变编码,但输入源乱了,输出一定跟着乱。这点容易被当成CONCAT的bug,其实是环境配置没对齐。










