2016-11-08 42 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