利用JSON_ARRAYAGG解决问题 -> ORA-01489: result of string concatenation is too long

问题: ORA-01489: result of string concatenation is too long

1. 查看Oracle数据库版本

如果数据库版本为18c或更高版本,则可以使用json_arrayagg替代xmlagg

SELECT * FROM V$VERSION;

2. 由于Oracle数据库版本是19c,所以使用JSON_ARRAYAGG

2.1 数据准备

创建students表,为后续演示JSON_ARRAYAGG功能做准备

DROP TABLE students;
COMMIT;

CREATE TABLE students
    ( student_id     NUMBER(6)
    , first_name     VARCHAR2(20)
    , last_name      VARCHAR2(25) 
    , email          VARCHAR2(40) 
    , phone_number   VARCHAR2(20)
    , join_date      DATE 
    , class_id       VARCHAR2(20)  
    , fees           NUMBER(8,2)
    , professor_id   NUMBER(6)
    , department_id  NUMBER(4) 
    ) ;
    
CREATE UNIQUE INDEX stu_id_pk ON students (student_id) ;
INSERT INTO students VALUES (100,'SMITH','JAMES','SMITH.JAMES@notreal.com','111.111.1245',TO_DATE('17-06-2003','DD-MM-YYYY'),'INS_CHAIRMAN',24000,NULL,NULL);
INSERT INTO students VALUES (101,'JOHNSON','JOHN','JOHNSON.JOHN@notreal.com','111.111.1246',TO_DATE('21-09-2005','DD-MM-YYYY'),'INS_VP',17000,100,90);
INSERT INTO students VALUES (102,'WILLIAMS','ROBERT','WILLIAMS.ROBERT@notreal.com','111.111.1247',TO_DATE('13-01-2001','DD-MM-YYYY'),'INS_VP',17000,100,90);
INSERT INTO students VALUES (103,'BROWN','MICHAEL','BROWN.MICHAEL@notreal.com','111.111.1248',TO_DATE('03-01-2006','DD-MM-YYYY'),'INS_STAFF',9000,102,60);
INSERT INTO students VALUES (104,'JONES','WILLIAM','JONES.WILLIAM@notreal.com','111.111.1249',TO_DATE('21-05-2007','DD-MM-YYYY'),'INS_STAFF',6000,103,60);
INSERT INTO students VALUES (105,'MILLER','DAVID','MILLER.DAVID@notreal.com','111.111.1250',TO_DATE('25-06-2005','DD-MM-YYYY'),'INS_STAFF',4800,103,60);
INSERT INTO students VALUES (106,'DAVIS','RICHARD','DAVIS.RICHARD@notreal.com','111.111.1251',TO_DATE('05-02-2006','DD-MM-YYYY'),'INS_STAFF',4800,103,60);
INSERT INTO students VALUES (107,'GARCIA','CHARLES','GARCIA.CHARLES@notreal.com','111.111.1252',TO_DATE('07-02-2007','DD-MM-YYYY'),'INS_STAFF',4200,103,60);
INSERT INTO students VALUES (108,'RODRIGUEZ','JOSEPH','RODRIGUEZ.JOSEPH@notreal.com','111.111.1253',TO_DATE('17-08-2002','DD-MM-YYYY'),'CL_PHY',12008,101,100);
INSERT INTO students VALUES (109,'WILSON','THOMAS','WILSON.THOMAS@notreal.com','111.111.1254',TO_DATE('16-08-2002','DD-MM-YYYY'),'CL_MATH',9000,108,100);
INSERT INTO students VALUES (110,'MARTINEZ','CHRISTOPHER','MARTINEZ.CHRISTOPHER@notreal.com','111.111.1255',TO_DATE('28-09-2005','DD-MM-YYYY'),'CL_MATH',8200,108,100);
INSERT INTO students VALUES (111,'ANDERSON','DANIEL','ANDERSON.DANIEL@notreal.com','111.111.1256',TO_DATE('30-09-2005','DD-MM-YYYY'),'CL_MATH',7700,108,100);
INSERT INTO students VALUES (112,'TAYLOR','PAUL','TAYLOR.PAUL@notreal.com','111.111.1257',TO_DATE('07-03-2006','DD-MM-YYYY'),'CL_MATH',7800,108,100);
INSERT INTO students VALUES (113,'THOMAS','MARK','THOMAS.MARK@notreal.com','111.111.1258',TO_DATE('07-12-2007','DD-MM-YYYY'),'CL_MATH',6900,108,100);

COMMIT;
2.2 利用JSON_ARRAYAGG进行拼接字符串
SELECT class_id,
      replace(JSON_ARRAYAGG(first_name || ' ' || last_name ORDER BY class_id RETURNING CLOB),'"','') AS retunring_val
FROM students
GROUP BY class_id;
-------------------------------------------------
输出结果:
CL_MATH         [WILSON THOMAS,THOMAS MARK,TAYLOR PAUL,ANDERSON DANIEL,MARTINEZ CHRISTOPHER]
CL_PHY          [RODRIGUEZ JOSEPH]
INS_CHAIRMAN    [SMITH JAMES]
INS_STAFF       [BROWN MICHAEL,GARCIA CHARLES,DAVIS RICHARD,MILLER DAVID,JONES WILLIAM]
INS_VP          [JOHNSON JOHN,WILLIAMS ROBERT]

这里SQL展示了JSON_ARRAYAGG的基本用法,即将first_name与last_name进行拼接,其他详细配置请参考SQL聚合函数 JSON_ARRAYAGG

注:CLOB 是内置类型,它将字符大对象 (Character Large Object) 存储为数据库表某一行中的一个列值.

3. 对JSON_ARRAYAGG查询结果进行处理

3.1 利用TRIM()去除首尾部的[]并替换’,‘为’;’
WITH TEMP AS (SELECT CLASS_ID,
                     TRIM(REPLACE(JSON_ARRAYAGG(FIRST_NAME || ' ' || LAST_NAME ORDER BY CLASS_ID RETURNING CLOB), '"',
                                  '')) AS RETUNRING_VAL
              FROM STUDENTS
              GROUP BY CLASS_ID)
SELECT REPLACE(TRIM(TRAILING ']' FROM
                    TRIM(LEADING '[' FROM RETUNRING_VAL)), ',', ';') AS RETUNRING_VAL
FROM TEMP;

4.解决问题时遇到的小知识点

4.1 listagg()列转行函数如果长度超过4000,会报Error,解决方法是LISTAGG(CAST(NAME AS VARCHAR(10000)), ‘,’)
4.2 Trim()参数
  • LEADING 开头字符
  • TRAILING 结尾字符
  • BOTH 开头和结尾字符
4.3 CAST可以将一种类型转换为另外一种类型
SELECT CAST('123.4567' AS NUMBER(10,2))  AS NUM FROM DUAL;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值