SQL CONCAT 怎么拼接多个字段?MySQL、PostgreSQL、SQL Server、Oracle 用法对比

月亮慢半拍
月亮慢半拍
发布时间:2026-08-23| 146人浏览过
原创

前言

在 SQL 里拼接多个字段,最容易被忽略的不是语法本身,而是数据库之间对 NULL、参数数量和版本支持的不同处理。本文按 MySQL、PostgreSQL、SQL Server、Oracle 分别拆开说明,并把哪些场景该用 CONCAT、哪些场景要改用 ||、+ 或 LISTAGG 讲清楚,方便你直接对照当前环境判断写法。

在 SQL 里拼接姓名、地址、标签这类多字段字符串时,很多人先想到的都是 CONCAT。但一旦数据库换成 MySQL、PostgreSQL、SQL Server 或 Oracle,NULL 的处理方式、参数数量限制、兼容版本要求都会变,表面上只是函数名相同,实际结果可能完全不同。

这篇文章按数据库分别整理常见写法和行为差异,重点放在最容易踩坑的 NULL 传播、连接操作符替代方案,以及多字段拼接时该怎么写更稳。看完你可以直接判断:当前环境下应该继续用 CONCAT,还是改用 ||、+、IFNULL/COALESCE,甚至 LISTAGG。

MySQL:支持多参数,但最怕 NULL 传染

MySQL 的 CONCAT 可以直接接收多个参数,不需要嵌套调用。字段、字符串字面量、函数返回值都可以按顺序参与拼接。

MySQL 与 SQL Server 中 NULL 对字符串拼接结果影响的避坑示意图
NULL 为什么会让拼接结果出错这张图聚焦最常见的实际错误:字段可空时,不同数据库的拼接结果为什么会突然变空。
SELECT CONCAT(first_name, ' ', last_name) FROM users;

它的关键特点是:只要任意一个参数是 NULL,整个结果就会返回 NULL。这也是 MySQL 里最常见的拼接错误来源。

为什么 MySQL 里要先处理可空字段

  • 空字符串 '' 不会影响拼接结果。
  • 但 NULL 会直接“污染”整个结果。
  • 字段可能为空时,通常要先用 IFNULL 或 COALESCE 兜底。
CONCAT(IFNULL(first_name, ''), ' ', IFNULL(last_name, ''))

如果表结构里这些字段允许为空,这一步最好不要省。否则 SQL 能执行,结果却可能整列变成 NULL。

PostgreSQL:可用 CONCAT,也常见 || 写法

PostgreSQL 9.1+ 提供了标准 CONCAT 函数,老版本或很多历史代码里也常见双竖线 || 作为连接符。

CONCAT 和 || 的区别要看清

这两种写法都能完成字符串拼接,但在语义上并不完全一样:

  • CONCAT(col1, col2) 会忽略 NULL 值。
  • col1 || col2 使用的是操作符写法,遇到 NULL 时表现和 CONCAT 不同,不能简单当成等价替代。

如果项目里希望写法统一、语义更直观,优先使用 CONCAT 会更稳妥。

SELECT CONCAT(first_name, ' ', middle_name, ' ', last_name) FROM people;

即使 middle_name 是 NULL,结果也会继续返回拼接后的字符串,而不是整行失败。

PostgreSQL 里还有一个容易忽略的返回值细节

PostgreSQL 的 CONCAT 至少要有一个非 NULL 参数;如果所有参数都是 NULL,返回的是空字符串,不是 NULL。这会影响后续判断逻辑,尤其是在你还要继续做比较、过滤或导出时。

SQL Server:2012+ 才有 CONCAT,旧版本还得靠 +

SQL Server 从 2012 开始支持 CONCAT。这个函数的设计目的很明确,就是避免使用 + 拼接时,一遇到 NULL 就把整条结果带成 NULL。

新旧版本写法差别很大

  • SQL Server 2012+:可以直接用 CONCAT。
  • SQL Server 2008 等旧版本:只能用 ISNULL 配合 + 手工处理。

新版本里,CONCAT 会自动把参数转成字符串,并跳过 NULL。

CONCAT(name, age)

这里如果 age 是 int,也会被隐式转换成字符串,不需要额外 CAST。

为什么不要把 + 和 CONCAT 混着写

  • 用 + 时,必须手动写 ISNULL(col, '')。
  • 漏掉任意一项,整行结果都可能变成 NULL。
  • 而 CONCAT 本身已经处理了这个问题。

所以在 SQL Server 2012+ 环境里,除非要兼容历史代码,否则没有必要继续坚持 + 拼接。

Oracle:原生 CONCAT 只支持两个参数

Oracle 的原生 CONCAT 只能接收两个参数,这一点和前面几个数据库差异很大。只要字段数量超过两个,就必须嵌套调用,或者直接改用 ||。

多字段拼接时,|| 才是主流写法

例如下面这种嵌套调用,虽然能用,但可读性一般,而且括号一多就容易写错:

CONCAT(CONCAT(first, ' '), last)

实际开发中更常见的是:

first || ' ' || middle || ' ' || last

这种写法更直观,也更适合多字段连续拼接。原文场景下,|| 对 NULL 的处理可以理解为“留空”,不会像 MySQL 的 CONCAT 那样直接中断整个结果。

拼接多行值时,不要误用 CONCAT

如果需求不是“把多个字段拼成一个字符串”,而是“把多行记录合并成一行文本”,那就已经不是 CONCAT 的适用场景了。在 Oracle 中应使用:

LISTAGG(email, '; ') WITHIN GROUP (ORDER BY email)

比如一个人有多个邮箱地址,需要按分号合并显示时,LISTAGG 才是对应方案。

最后要记住的判断标准

同样是拼接多个字段,不同数据库真正拉开差距的不是函数名,而是三个细节:是否支持多参数、遇到 NULL 怎么处理、有没有版本限制。

MySQL、PostgreSQL、SQL Server、Oracle 在多字段拼接时的 NULL 处理和参数支持差异对比图
四种数据库的拼接规则差异用一张对比图快速看清四种数据库在多字段拼接时最容易混淆的行为差异。
  • MySQL:支持多参数,但任意参数为 NULL 时整体返回 NULL。
  • PostgreSQL:CONCAT 会忽略 NULL,也常见 || 写法,但两者语义不能混看。
  • SQL Server:CONCAT 需要 2012+,旧版本仍要依赖 ISNULL + +。
  • Oracle:原生 CONCAT 只支持两个参数,多字段通常直接用 ||;多行聚合则用 LISTAGG。

真正上线前,最好先确认字段是否允许为空,再结合数据库类型选写法。只记住 CONCAT 这个名字远远不够,NULL 行为和版本边界才是决定结果是否正确的关键。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。