Skip to Main Content
  • Questions
  • problem of inserting a long string of characters

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, achraf.

Asked: June 18, 2018 - 12:30 pm UTC

Last updated: June 22, 2018 - 2:54 am UTC

Version: 11 g

Viewed 1000+ times

You Asked

Hello Team ,


I'm trying to insert into a table " TEST COM " the result of selecting rows of another table.
I used the wm_concat function .


/**********/

insert into COMMENTAIRE_TEST (SELECT wm_concat((DBMS_LOB.SUBSTR(COM_TEXTE,4000,1))) as test
FROM commentaire
--where COM_NUMREF=1416
GROUP BY COM_NUMREF)

/************/

when I execute the query, I have the following error

/*****************************************************************************
Rapport d'erreur -
Erreur SQL : ORA-22835: Taille de tampon insuffisante pour la conversion de CLOB en CHAR ou de BLOB en RAW (réelle : 46972, maximum : 4000)
22835. 00000 - "Buffer too small for CLOB to CHAR or BLOB to RAW conversion (actual: %s, maximum: %s)"
*Cause: An attempt was made to convert CLOB to CHAR or BLOB to RAW, where
the LOB size was bigger than the buffer limit for CHAR and RAW
types.
Note that widths are reported in characters if character length
semantics are in effect for the column, otherwise widths are
reported in bytes.
*Action: Do one of the following
1. Make the LOB smaller before performing the conversion,
for example, by using SUBSTR on CLOB
2. Use DBMS_LOB.SUBSTR to convert CLOB to CHAR or BLOB to RAW.
/*********************************************************************************

I need your help please :)

thank you in advance

and Connor said...

wm_concat is no longer supported, so it is probably time to move away from that anyway.

We do have the LISTAGG function, but currently that has the same limitation, ie, it returns a varchar2 not a clob.

A workaround is to use XMLAGG function to do the concatenation, eg

SQL> select rtrim(xmlagg(xmlelement(e,object_name,',').extract('//text()') order by object_name).GetClobVal(),',')
  2  from   dba_objects
  3  where  owner = 'SCOTT';

RTRIM(XMLAGG(XMLELEMENT(E,OBJECT_NAME,',').EXTRACT('//TEXT()')ORDERBYOBJECT_NAME
--------------------------------------------------------------------------------
BONUS,CLONE_TAB,CUSTOMERS,DEPT,DEPT_PK,EMP,EVALUATE_STUFF,MY_NUM_LIST,MY_PROC,MY...


Rating

  (2 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

ach ben, June 19, 2018 - 9:09 am UTC


First thank you for your feedback,


I tested your solution with xmlagg but I have the following error

select rtrim(xmlagg(xmlelement(e,COM_TEXTE,',').extract('//text()')).GetClobVal(),',')
from commentaire;

ORA-31061: Erreur XDB : special char to escaped char conversion failed.
31061. 00000 - "XDB error: %s"
*Cause: The specified error occurred in XDB.
*Action: Correct the error or contact Oracle Support Services.

Connor McDonald
June 22, 2018 - 2:54 am UTC

Perhaps try a custom aggregate then

SQL> create or replace
  2  type listagg_clob
  3  as object
  4  (
  5    l_result clob,
  6
  7    static function odciaggregateinitialize( ctx in out listagg_clob ) return number,
  8    member function odciaggregateiterate( self in out listagg_clob, value in clob ) return number,
  9    member function odciaggregateterminate( self in listagg_clob, returnvalue out clob, flags in number ) return number,
 10    member function odciaggregatemerge( self in out listagg_clob, ctx2 in listagg_clob )  return number
 11  );
 12  /

Type created.

SQL>
SQL>
SQL> create or replace
  2  type body listagg_clob
  3  is
  4
  5    static function odciaggregateinitialize( ctx in out listagg_clob )  return number  is
  6      l_tmp clob;
  7    begin
  8      dbms_lob.createtemporary( l_tmp, true, dbms_lob.call );
  9      ctx := listagg_clob( l_tmp );
 10      return odciconst.success;
 11    end;
 12
 13    member function odciaggregateiterate( self in out listagg_clob, value in clob )  return number  is
 14    begin
 15      if dbms_lob.getlength( self.l_result ) > 0 then
 16        dbms_lob.append( self.l_result, ',' );
 17      end if;
 18      dbms_lob.append( self.l_result, value );
 19      return odciconst.success;
 20    end;
 21
 22    member function odciaggregateterminate( self in listagg_clob, returnvalue out clob, flags in number)  return number  is
 23    begin
 24       returnvalue := self.l_result;
 25       return odciconst.success;
 26     end;
 27
 28    member function odciaggregatemerge( self in out listagg_clob, ctx2 in listagg_clob )  return number  is
 29    begin
 30       dbms_lob.append( self.l_result, ctx2.l_result );
 31       return odciconst.success;
 32     end;
 33  end;
 34  /

Type body created.

SQL>
SQL>
SQL> create or replace
  2  function listaggc( input clob )
  3  return clob
  4  parallel_enable aggregate
  5  using listagg_clob;
  6  /

Function created.

SQL>
SQL> select listaggc(ename) from emp;

LISTAGGC(ENAME)
--------------------------------------------------------------------------------
SMITH,ALLEN,WARD,JONES,MARTIN,BLAKE,CLARK,SCOTT,KING,TURNER,ADAMS,JAMES,FORD,MIL

1 row selected.

SQL>


Other workaround?

Duke Ganote, June 22, 2018 - 5:07 pm UTC

More to Explore

SQL

The Oracle documentation contains a complete SQL reference.