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

alchn picture alchn · Aug 23, 2012 · Viewed 38k times · Source

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...

Answer

mlvnd picture mlvnd · Oct 8, 2012

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

        );