我的表包含一个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中执行此操作,但不知道如何操作。任何帮助都非常感谢。谢谢!
答案 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