如何在select语句中动态添加列名(Oracle)

时间:2016-11-08 16:36:29

标签: sql oracle oracle11g dynamic-sql

我的表包含一个CLOB字段,其长度可能超过32767字节或字符。这意味着,如果我想从此CLOB字段中提取所有字符,我必须将CLOB拆分为块并将每个块作为SELECT查询中的不同列传递言。

所以我有这个问题:

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中执行此操作,但不知道如何操作。任何帮助都非常感谢。谢谢!

1 个答案:

答案 0 :(得分: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