SELECT as much data from CLOB to VARCHAR2 as possible, with multibyte chars in the data

39,574

Solution 1

Jeffrey's thinking process is ok, but alchn is also right. Just ran into this same problem and here is my solution. You'll have to be able to create a function though:

Create Or Replace Function clob_substr(p_clob   In Clob
                                      ,p_offset In Pls_Integer
                                      ,p_length In Pls_Integer) Return Varchar2 Is
Begin
  Return substrb(dbms_lob.substr(p_clob
                                ,p_length
                                ,p_offset)
                ,1
                ,p_length);
End;
/

Here is a demo of it's use:

Select c
      ,clob_substr(c
                  ,1
                  ,4000)
  From (

        Select xmlelement("t", rpad('é', 4000, 'é'), rpad('é', 4000, 'é')).extract('//text()').getclobval() c
          From dual

        );

Solution 2

Maybe truncate the resulting varchar2 with SUBSTR:

SELECT SUBSTRB( DBMS_LOB.SUBSTR( description, 4000, 1 ), 1, 4000) FROM table
Share:
39,574
alchn
Author by

alchn

Updated on August 15, 2022

Comments

  • alchn
    alchn over 1 year

    Multi-byte characters had caused me a lot of pain.

    Any suggestion for this problem?

    I have a CLOB field that might contains some multi-byte characters, and I need to select in SQL and convert this field into a string for downstream process, currently I am using:

    SELECT DBMS_LOB.SUBSTR( description, 4000, 1 ) FROM table
    

    But the 4000 in above command is in length of characters, rather than bytes. So I had to change to 3000 to handle any multi-byte characters that might have crept into the data else buffer size error will occur.

    The problem is for records that do not contain multibyte character, it might unnecessarily truncated more data than it need to. (The 4000 is the string limitation, we can/had to live with that.)

    Is there a way to do something in equivalent of:

    SELECT DBMS_LOB.SUBSTR( description, 4000bytes, 1 ) FROM table
    

    That way I can get as much data out as possible.

    Note: I am not allowed to create temp tables/views, not using PL/SQL, only SQL SELECT...