2013-09-26 126 views
6
Select TO_CLOB(a)|| TO_CLOB(b)|| TO_CLOB(c) || TO_CLOB(d) 
    from table1 

上面的查詢沒有正確地將數據後臺打印到文本文件中。錯誤在第191行:ORA-01489:字符串連接的結果太長

而,

Select a||b||c||d 
    from table1. 

在線191結束於

ERROR:ORA-01489:字符串連接的結果是太長。

請幫忙!!!

+0

一些有用的。提示:http://stackoverflow.com/questions/14864055/listagg-function-and-ora-01489-result-of-string-concatenation-is-too-long – Sampath

回答

0

如何增加LONG的值?您可能必須將long變量增加到更高的值。有關詳細說明,請點擊here

例子:

SET LONG 100000; 
SPOOL test_clob.txt 
SELECT to_clob(lpad('A',4000,'A')) 
     ||'B' 
     ||to_clob(lpad('C',4000,'C')) 
     ||'D' 
     ||to_clob(lpad('E',4000,'E')) 
     ||'F' 
    FROM dual; 
SPOOL OFF; 

你的第二個查詢將返回錯誤,因爲 (||)運算符的查詢試圖返回VARCHAR2的CONCAT,其中有4000個字符的限制和獲得突破。

+1

SET LONG是一個系統參數或者是否僅適用於正在啓動的查詢? –

+1

@DavideInglima從文檔:*「SET語句將值分配給影響服務器或客戶端操作的不同類型的變量。」* –

-1

顯示CLOB時SQL * Plus硬編碼行大小81,似乎沒有辦法繞過它。因此,如果要生成要加載到其他數據庫的csv文件,則會遇到解析這些額外換行符的問題。

最終的解決方案是使用PL/SQL。例如,從表「XYZ」 genarate一個逗號分隔的csv文件,使用下面的代碼:

set lin 32766 
set serveroutput on size unlimited 

DECLARE 
    TYPE arraytable IS TABLE OF xyz%ROWTYPE; 
    myarray arraytable; 
    CURSOR c IS 
    select * from xyz ; 
BEGIN 
    OPEN c; 
    LOOP 
     FETCH c BULK COLLECT INTO myarray LIMIT 10000; 
     FOR i IN 1 .. myarray.COUNT 
      LOOP 
       DBMS_OUTPUT.PUT_LINE(
        myarray(i).col1||','|| 
        myarray(i).col2||','|| 
        myarray(i).col3||','|| 
        myarray(i).col4; 
     END LOOP; 
     EXIT WHEN c%NOTFOUND; 
    END LOOP; 
END; 
/

這種方法的好處是,這甚至用long類型的作品!

+0

您仍在連接VARCHAR> 4000字節。 –

+0

@ Jean-Francois Savard,No. PL/SQL的輸出不再是VARCHAR。因此它不會受到4000尺寸限制。 – user3398079

1

VARCHAR2限於4000個字節。如果你得到這個錯誤

錯誤在第191行:ORA-01489:字符串連接的結果太長 長。

然後很明顯連接超過4000字節。

現在該怎麼辦?

您的第一個使用CLOB的解決方案是正確的。

select TO_CLOB(a)|| TO_CLOB(b)|| TO_CLOB(c) || TO_CLOB(d) 

好像你真正的問題是保存到文件

上面的查詢不正確後臺數據導入文本文件。

雖然您沒有發佈如何將生成的clob保存到文件中,但我相信您沒有正確執行此操作。如果您嘗試使用VARCHAR2以相同的方式保存文件,那麼您做錯了。

您需要先使用dbms_lob.read從數據庫中讀取clob,然後使用utl_file.put_raw寫入文件。

DECLARE 
    position NUMBER := 1; 
    byte_length NUMBER := 32760; 
    length NUMBER; 
    vblob BLOB; 
    rawlob RAW(32760); 
    temp NUMBER; 
    output utl_file.file_type; 
BEGIN 
    -- Last parameter is maximum number of bytes returned. 
    -- wb stands for write byte mode 
    output := utl_file.fopen('DIR', 'filename', 'wb', 32760); 

    position := 1; 
    select dbms_lob.getlength(yourLob) 
    into len 
    from somewhere 
    where something; 

    temp := length; 

    select yourLob 
    into vlob 
    from somewhere 
    where something; 

    IF len < 32760 THEN 
     utl_file.put_raw(output, vblob); 
     -- Don't forget to flush 
     utl_file.fflush(output); 
    ELSE -- write part by part 
     WHILE position < len AND byte_length > 0 
     LOOP 
      dbms_lob.read(vblob, byte_length, position, rawlob); 

      utl_file.put_raw(output,rawlob); 

      -- You must admit, you would have forgot to flush. 
      utl_file.fflush(output); 

      position := position + byte_length; 

      -- set the end position if less than 32000 bytes 
      temp := temp - bytelen; 
      IF temp < 32760 THEN 
       byte_length := temp; 
      END IF; 
    END IF; 
END;