Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 809
alchn Avatar asked Aug 23 '12 05:08

alchn


People also ask

What is the difference between VARCHAR2 and CLOB?

The difference between the 2 types is that in VARCHAR2 you have to specify the length of the stored string and that length is limited to 4000 characters while CLOB can store up to 128 terabytes of character data in the database.

How do I save more than 4000 characters in Oracle?

For strings greater than 4000 use a CLOB. you can use CLOB column.


1 Answers

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

        );
like image 141
mlvnd Avatar answered Sep 21 '22 23:09

mlvnd