Oracle 多行记录合并连接聚合字符串有哪几种方法

来源:建站技术作者:越南程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《Oracle 多行记录合并连接聚合字符串有哪几种方法》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Oracle 多行记录合并连接聚合字符串有哪几种方法》有用,将其分享出去将是对创作者最好的鼓励。

在Oracle数据库的业务查询场景中,将同一分组下的多行字符串字段值合并为单个字符串是常见需求,比如汇总同一订单的所有商品名称、统计同一部门的所有员工工号等。不同的实现方式在兼容性、性能和功能支持上存在差异,开发者需要结合实际情况选择。

Oracle 多行记录合并连接聚合字符串有哪几种方法

Oracle多行记录合并的常用方法

1. 使用wmsys.wm_concat函数

wmsys.wm_concat是Oracle早期提供的字符串聚合函数,属于内部函数,使用门槛较低,语法简单。它默认会将合并后的字符串用逗号分隔,不需要额外指定分隔符参数。

示例表结构如下,我们基于该表演示合并操作:

部门ID员工姓名
10张三
10李四
20王五

使用wmsys.wm_concat合并同一部门的员工姓名:

-- 按部门ID分组,合并员工姓名
SELECT 部门ID, wmsys.wm_concat(员工姓名) AS 员工列表
FROM 员工表
GROUP BY 部门ID;

该方法的优点是语法简单,兼容Oracle 10g及以上大部分版本;缺点是它是Oracle未公开的内部函数,在12c及以后版本中已经被废弃,部分新版本中可能无法使用,且不支持自定义分隔符,合并后的字符串顺序是随机的。

2. 使用LISTAGG函数

LISTAGG是Oracle 11g R2版本官方推出的字符串聚合函数,属于标准功能,稳定性和兼容性更好,支持自定义分隔符和排序规则。

基础语法如下:

LISTAGG(合并字段, 分隔符) WITHIN GROUP (ORDER BY 排序字段)

同样基于上述员工表,使用LISTAGG实现按部门合并员工姓名,用逗号分隔,按姓名升序排列:

-- 按部门ID分组,合并员工姓名,用逗号分隔,按姓名升序排序
SELECT 部门ID, 
       LISTAGG(员工姓名, ',') WITHIN GROUP (ORDER BY 员工姓名) AS 员工列表
FROM 员工表
GROUP BY 部门ID;

如果需要处理合并后字符串过长的情况,可以使用LISTAGG的截断功能,避免超过VARCHAR2的最大长度限制:

-- 合并字符串超过100字符时截断并添加省略号
SELECT 部门ID, 
       LISTAGG(员工姓名, ',') WITHIN GROUP (ORDER BY 员工姓名) 
       ON OVERFLOW TRUNCATE '...' 
       AS 员工列表
FROM 员工表
GROUP BY 部门ID;

LISTAGG的优点是官方支持,功能完善,支持自定义分隔符和排序,性能也优于wmsys.wm_concat;缺点是仅支持Oracle 11g R2及以上版本,低版本数据库无法使用。

3. 使用XMLAGG函数

XMLAGG是基于XML处理的聚合函数,兼容性较好,支持Oracle 9i及以上版本,也支持自定义分隔符和排序,适合低版本数据库使用。

实现示例如下,合并同一部门的员工姓名,用逗号分隔:

-- 按部门ID分组,使用XMLAGG合并员工姓名
SELECT 部门ID,
       RTRIM(XMLAGG(XMLELEMENT(e, 员工姓名 || ',') ORDER BY 员工姓名).EXTRACT('//text()').getClobVal(), ',') AS 员工列表
FROM 员工表
GROUP BY 部门ID;

上述代码中,XMLELEMENT用于将每个员工姓名拼接上分隔符,XMLAGG进行聚合,EXTRACT提取文本内容,RTRIM用于去掉最后一个多余的逗号。该方法的优点是兼容性好,支持低版本Oracle,也支持自定义分隔符和排序;缺点是语法相对复杂,可读性较差,且合并后的结果类型是CLOB,如果需要VARCHAR2类型还需要额外转换。

4. 使用自定义聚合函数

如果上述内置函数都无法满足需求,比如需要支持特殊的聚合逻辑,还可以自定义聚合函数实现多行字符串合并。首先需要定义一个对象类型来实现聚合逻辑:

-- 定义字符串聚合的对象类型
CREATE OR REPLACE TYPE str_agg_type AS OBJECT
(
  total CLOB,
  -- 初始化方法
  STATIC FUNCTION odciaggregateinitialize(sctx IN OUT str_agg_type) RETURN NUMBER,
  -- 迭代方法,处理每一行数据
  MEMBER FUNCTION odciaggregateiterate(self IN OUT str_agg_type, value IN VARCHAR2) RETURN NUMBER,
  -- 终止方法,返回最终结果
  MEMBER FUNCTION odciaggregateterminate(self IN str_agg_type, returnvalue OUT CLOB, flags IN NUMBER) RETURN NUMBER,
  -- 合并方法,处理并行聚合
  MEMBER FUNCTION odciaggregatemerge(self IN OUT str_agg_type, ctx2 IN str_agg_type) RETURN NUMBER
);
/

然后实现该对象类型的方法:

CREATE OR REPLACE TYPE BODY str_agg_type IS
  -- 初始化
  STATIC FUNCTION odciaggregateinitialize(sctx IN OUT str_agg_type) RETURN NUMBER IS
  BEGIN
    sctx := str_agg_type(NULL);
    RETURN odciconst.success;
  END odciaggregateinitialize;
  
  -- 迭代处理每一行,拼接字符串
  MEMBER FUNCTION odciaggregateiterate(self IN OUT str_agg_type, value IN VARCHAR2) RETURN NUMBER IS
  BEGIN
    IF self.total IS NULL THEN
      self.total := value;
    ELSE
      self.total := self.total || ',' || value;
    END IF;
    RETURN odciconst.success;
  END odciaggregateiterate;
  
  -- 返回最终结果
  MEMBER FUNCTION odciaggregateterminate(self IN str_agg_type, returnvalue OUT CLOB, flags IN NUMBER) RETURN NUMBER IS
  BEGIN
    returnvalue := self.total;
    RETURN odciconst.success;
  END odciaggregateterminate;
  
  -- 合并并行结果
  MEMBER FUNCTION odciaggregatemerge(self IN OUT str_agg_type, ctx2 IN str_agg_type) RETURN NUMBER IS
  BEGIN
    IF ctx2.total IS NOT NULL THEN
      IF self.total IS NULL THEN
        self.total := ctx2.total;
      ELSE
        self.total := self.total || ',' || ctx2.total;
      END IF;
    END IF;
    RETURN odciconst.success;
  END odciaggregatemerge;
END;
/

最后创建自定义聚合函数:

-- 创建自定义聚合函数
CREATE OR REPLACE FUNCTION str_agg(input VARCHAR2) RETURN CLOB
AGGREGATE USING str_agg_type;
/

使用自定义函数合并员工姓名:

-- 使用自定义聚合函数合并字符串
SELECT 部门ID, str_agg(员工姓名) AS 员工列表
FROM 员工表
GROUP BY 部门ID;

自定义聚合函数的优点是灵活性极高,可以根据需求定制聚合逻辑,兼容性也较好;缺点是实现步骤繁琐,需要创建类型和函数,维护成本较高。

不同方法的适用场景总结

  • 如果使用Oracle 11g R2及以上版本,优先选择LISTAGG函数,功能完善且官方支持。
  • 如果使用Oracle 11g R2以下版本,且没有特殊分隔符需求,可以选择wmsys.wm_concat,但要注意新版本兼容性问题。
  • 如果使用低版本Oracle,且需要自定义分隔符和排序,可以选择XMLAGG函数。
  • 如果有特殊的聚合逻辑,内置函数无法满足,可以选择自定义聚合函数。

Oracle多行记录合并字符串聚合wmsys.wm_concatlistagg修改时间:2026-06-16 00:39:38

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。