导读:本期聚焦于小伙伴创作的《Oracle中如何实现字符串汇总?有哪些常用方法?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Oracle中如何实现字符串汇总?有哪些常用方法?》有用,将其分享出去将是对创作者最好的鼓励。

在Oracle数据库的业务场景中,经常需要将同一分组下的多行字符串数据合并为一个完整的字符串,比如将某个部门下所有员工的姓名合并展示,或者将订单关联的所有商品名称汇总成一个字段,这类需求就是字符串汇总。不同的Oracle版本和场景适合使用不同的汇总方法,下面将逐一介绍。

Oracle中如何实现字符串汇总?有哪些常用方法?

方法一:使用LISTAGG函数

LISTAGG是Oracle 11g R2版本引入的原生字符串聚合函数,是目前官方推荐的首选字符串汇总方法,语法规范且功能完善。

LISTAGG的基本语法如下:

LISTAGG(需要汇总的字段, 分隔符) WITHIN GROUP (ORDER BY 排序字段) [OVER (PARTITION BY 分组字段)]

如果需要按部门汇总员工姓名,使用逗号作为分隔符,按员工入职时间排序,示例代码如下:

SELECT 
    dept_id,
    LISTAGG(emp_name, ',') WITHIN GROUP (ORDER BY hire_date) AS emp_names
FROM emp_table
GROUP BY dept_id;

LISTAGG的优势是支持自定义分隔符和排序规则,官方维护稳定,但是存在两个限制:一是Oracle 11g R2以下版本不支持,二是汇总的字符串总长度不能超过4000字节,否则会抛出字符串超长错误。

方法二:使用WM_CONCAT函数

WM_CONCAT是Oracle早期版本提供的非公开字符串聚合函数,在Oracle 10g、11g版本中广泛使用,但是Oracle 12c及以后版本已经移除了这个函数,不建议在新项目中使用。

WM_CONCAT的使用非常简单,不需要指定分隔符,默认使用逗号分隔,示例代码如下:

SELECT 
    dept_id,
    WM_CONCAT(emp_name) AS emp_names
FROM emp_table
GROUP BY dept_id;

这个函数的优势是兼容低版本Oracle,不需要复杂配置,但是缺点也很明显:首先是官方不推荐使用,后续版本可能完全移除,其次是默认分隔符无法修改,也不支持自定义排序规则,汇总的字符串同样有长度限制。

方法三:自定义聚合函数

如果需要兼容更低版本的Oracle,或者需要汇总超长字符串避免4000字节的限制,可以自定义聚合函数实现字符串汇总功能。

首先创建一个用于拼接字符串的类型:

CREATE OR REPLACE TYPE str_agg_type AS OBJECT(
    total_str CLOB,  -- 使用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_str IS NULL THEN
            self.total_str := value;
        ELSE
            self.total_str := self.total_str || ',' || 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_str;
        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_str IS NOT NULL THEN
            self.total_str := self.total_str || ',' || ctx2.total_str;
        END IF;
        RETURN odciconst.success;
    END odciaggregatemerge;
END;
/

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

CREATE OR REPLACE FUNCTION custom_str_agg(input_str VARCHAR2) RETURN CLOB
AGGREGATE USING str_agg_type;
/

使用自定义函数的示例:

SELECT 
    dept_id,
    custom_str_agg(emp_name) AS emp_names
FROM emp_table
GROUP BY dept_id;

自定义聚合函数的优势是可以突破4000字节的长度限制,兼容所有Oracle版本,还可以自定义分隔符和拼接逻辑,但是需要手动创建类型和函数,维护成本相对较高。

不同方法的选择建议

可以根据实际场景选择合适的方法:

  • 如果使用Oracle 11g R2及以上版本,且汇总字符串长度不超过4000字节,优先选择LISTAGG函数,稳定且易用。
  • 如果是老项目且使用Oracle 10g、11g版本,暂时可以保留WM_CONCAT的使用,但新功能不建议引入。
  • 如果需要汇总超长字符串,或者需要兼容极低版本的Oracle,选择自定义聚合函数的方案。

在使用字符串汇总功能时,还需要注意如果汇总字段存在NULL值,大部分汇总方法会直接忽略NULL值,不会将其计入结果,如果需要处理NULL值可以提前使用NVL函数将NULL转换为指定内容。

Oracle字符串汇总listaggwm_concat聚合函数修改时间:2026-06-22 00:00:32

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