2016-11-08 72 views
2

我的表包含一個CLOB字段,其​​長度可以超過32767個字節或字符。這意味着,如果我想從此CLOB字段中提取所有字符,則必須將CLOB分成塊,並將每個塊作爲SELECT查詢語句中的不同列進行傳遞。如何在SELECT語句中動態添加列名(Oracle)

所以我有這個疑問:

SELECT dbms_lob.Substr(clob_field, dbms_lob.Getlength(clob_field), 1) AS data 
FROM some_table 

如果clob_field太大這是行不通的。我的想法是製作長度爲2000的塊,並且對於每個塊,在SELECT聲明中添加一列。

理念的概念:

var a = 1 
var b = 2000 
chunkAmountList = 1+(dbms_lob.Getlength(clob_field) mod 2000) 
statement = "SELECT " 

BEGIN 
for chunk in chunkAmountList 
    statement = statement + "dbms_lob.Substr(clob_field, b, a) as data" 
    a = a + 2000 
    b = b + 2000 
endloop 
END 

statement = statement + "FROM some_table" 
statement.execute() 

這將導致相同名稱不同的列(這是我想要的)。所以,如果clob_field具有5000的長度,我想這是一個結果:

data     data     data 
----     ----     ---- 
"first 2000 chars" "second 2000 chars" "last 1000 chars" 

我想這樣做在Oracle中,但不知道怎麼樣。任何幫助真的很感激。謝謝!

+3

我會使用2048個字符而不是2000;它更適合於32767.對於每個「塊」的字符串都有一個新的行,這也是比較正常的。然後你可以用一個連接來代替動態SQL。 *(創建一個16行,其中的值爲1到16的表,加入這個行並選擇行的id和第n個2048個字符。)*然後,您也只需要返回具有值的行,而不是可能會返回16個字段,其中一些字段爲空。是否有一個原因,它必須分裂到多個*領域*? – MatBailie

+4

你提取所有數據的目的是什麼?有人肯定會讀它嗎?他們用什麼方法訪問數據庫?一些描述的呈現網站,或者他們直接用SQL * Plus之類的東西來讀取它。 – Ben

+2

您是否知道CLOB可能包含幾個TBytes?數字ob列不得超過1000,這不適合。 –

回答

0

通常的做法是將一個大對象分成多行,而不是你不能把它分成多列,但如果你這樣做,你經常會得到比你需要的更多的列,或者可能發現自己超過允許的最大列數。

在爲此創建解決方案時,您需要了解DBMS_LOB.SUBSTR(lob, size, index)的參數。第二個參數是你想要返回的substr的大小,所以它的值應該保持不變,你只需要增加索引。

這裏是一個可能的實現,出於演示的目的,我使用一個大小爲5,但你可以很容易地用更大尺寸改爲:

WITH sample_data(id, lob) AS (
    SELECT 1 
     , 'this is a test' 
    FROM dual 
), r(id, lob, len, seq, str) AS (
    SELECT 1 
     , lob 
     , dbms_lob.getlength(lob) 
     , 1 
     , dbms_lob.substr(lob, 5, 1) 
    FROM sample_data 
    UNION ALL 
    SELECT id 
     , lob 
     , len 
     , seq + 1 
     , dbms_lob.substr(lob, 5, 1 + 5 * seq) 
    FROM r 
    WHERE 1 + 5 * seq < len 
) 
SELECT * FROM r; 

     ID LOB     LEN  SEQ STR  
---------- -------------- ---------- ---------- ---------- 
     1 this is a test   14   1 this  
     1 this is a test   14   2 is a  
     1 this is a test   14   3 test  

如果你真的想多列,而不是多行,你可以通過改變最後一行轉動上述結果:

SELECT * FROM r PIVOT (max(str) str for seq in (1, 2, 3)); 

     ID LOB     LEN 1_STR 2_STR 3_STR 
---------- -------------- ---------- -------- -------- -------- 
     1 this is a test   14 this  is a  test  

你可以儘可能多號添加到seq in (...)條款,因爲你需要:

SELECT * FROM r PIVOT (max(str) str for seq in (1, 2, 3, 4, 5, 6)); 

     ID LOB     LEN 1_STR 2_STR 3_STR 4_STR 5_STR 6_STR 
---------- -------------- ---------- -------- -------- -------- -------- -------- -------- 
     1 this is a test   14 this  is a  test