2016-11-08 1 views
2

테이블에 길이가 32767 바이트 또는 문자 이상인 CLOB 필드가 있습니다. 즉, CLOB 필드에서 모든 문자를 추출하려면 CLOB을 청크로 분할하고 각 청크를 SELECT 쿼리 문에 다른 열로 전달해야합니다. clob_field가 너무 큰 경우select 문에 동적으로 열 이름을 추가하는 방법 (Oracle)

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

이 작동하지 않습니다 :

그래서 나는이 쿼리가 있습니다. 내 생각은 길이가 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" 

을 나는 오라클에서이 작업을 수행하기를 원하지만 방법은 모르겠어요. 어떤 도움이라도 대단히 감사합니다. 감사!

+3

2000 대신 2048자를 사용합니다. 그것은 32767에 더 깔끔하게 맞습니다. 문자열의 각 "조각"에 대해 새로운 행을 갖는 것이 더 일반적입니다. 그런 다음 동적 SQL 대신 결합을 사용하여이를 수행 할 수 있습니다. * (값이 1에서 16까지 인 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        
관련 문제