2012-08-23 19 views
7

多字節字符給我帶來了很多痛苦。儘可能多地從CLOB中選擇數據到VARCHAR2,在數據中使用多字節字符

對此問題的任何建議?

我有一個CLOB字段威力包含一些多字節字符,我需要在SQL選擇和這個字段轉換爲下游工序的字符串,目前我使用:

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

但是上述命令中的4000是字符長度,而不是字節長度。所以我不得不改變爲3000來處理可能進入數據的任何多字節字符,否則會發生緩衝區大小錯誤。

問題是不包含多字節字符的記錄,它可能會不必要地截斷更多的數據比它需要。 (4000是字符串的限制,我們可以/不得不住在一起)

有沒有辦法做一些相當於:

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

這樣我可以得到儘可能多的數據出來儘可能。

注:我不允許創建臨時表/視圖,不使用PL/SQL,只有SQL SELECT ...

回答

4

也許與SUBSTR截斷導致VARCHAR2:

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

難道不應該是「......與SUBSTRB」? (SUBSTRB而不是SUBSTR) –

+1

出於興趣:如果前3999個字符是一個字節長,而第4000個字符是多字節,會發生什麼情況?它不會返回位置4000處的錯誤字符(因爲它將多字節字符的第一個字節解釋爲單字節字符)? –

+2

否Jeffery無法工作,如果'description'包含多字節字符,則最內層的DBMS_LOB.SUBSTR在到達SUBSTRB之前已經遇到字符串緩衝區錯誤。 – alchn

7

傑弗裏的思維過程是好的,但alchn也是對的。剛剛遇到同樣的問題,這是我的解決方案。你必須要能夠創造雖然功能:

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; 
/

這裏是它的一個演示的使用:

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

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

     ); 
+1

我在https://bitbucket.org/janihur/orasql-ex/src/tip/clob-2.sql上創建了一個基於此答案的綜合(我希望!)示例 – user272735

+0

我已經測試並確認使用此函數比Jeffrey的解決方案效果更好。但是,我不明白爲什麼。這不是做同樣的事情,但在一個功能,而不是內聯?爲什麼在這裏有所作爲? – KStensland

+0

我懷疑區別在於PL/SQL中的varchar2可以達到32,767字節,而在SQL(至少在11g和更早版本中),最大值是4,000字節。 –

相關問題