반응형
제품 : JDBC

작성날짜 :

FILE을 CLOB에 INSERT하고, 반대로 컬럼을 읽어 FILE로 WRITE하는 JDBC PROGRAM 예제 (JDBC 8.1 이상)



PURPOSE

text file을 읽어서 CLOB column 에 저장하는 방법과, CLOB column의 데이타를
읽어서 file로 write하는 방법을 예제를 통해서 살펴본다.


Explanation



oracle.sql package에서 제공하는 CLOB class를 이용한다.
file의 내용을 읽어 CLOB type에 저장할 때는 CLOB.getCharacterOutputStream을
이용하고, 반대로 file에 write를 위해 CLOB type을 읽을 때는
clob.getCharacterStream() 를 이용한다.

Oracle JDBC driver 8.1.x 이상 version의 classes12.zip file이 CLASSPATH에
지정되어 있어야 한다. JDK는 1.2 이상을 사용한다.

[참고] 화일을 이용하지 않고 직접 text를 CLOB에 입력하고, 입력된 CLOB
데이타를 화면에 display하기 위해서는 아래 bulletin을 참고한다.
<Bulletin No: 19360>: Subject: ORACLE.SQL.CLOB CLASS를 이용하여
4000 BYTES이상의 CLOB TEXT 데이타를 저장하고, 조회하는 예제

Example


1. 테이블의 생성과 데이타 입력

미리 다음 작업이 수행되어 있어야 하며, 이 작업도 java application내에
statement.execute를 통해 포함시킬 수 있다.

sqlplus scott/tiger
SQL> create table test_clob(id number, c clob);
SQL> insert into test_clob values (1, empty_clob());

2. ClobFile.java

다음 내용을 ClobFile.java라는 이름으로 생성한 후,

os>javac ClobFile.java
os>java ClobFile
후 out.txt file내용을 확인하고, scott.TEST_CLOB table의 데이타도 조회하여
수해이 잘 되었는지 확인한다.

import java.sql.*;
import java.io.*;
import java.util.*;
import oracle.jdbc.driver.*;

import oracle.sql.*;

public class ClobFile {

public static void main (String args []) throws Exception {

try {
Connection conn;

DriverManager.registerDriver( new oracle.jdbc.driver.OracleDriver() );
conn = DriverManager.getConnection( "jdbc:oracle:thin:@krint-5:1521:ORA920"

, "scott","tiger" );

conn.setAutoCommit (false);

CLOB clob = null;

Statement stmt = conn.createStatement ();

String cmd = "select * from test_clob for update";
ResultSet rset = stmt.executeQuery(cmd);
while (rset.next())
clob = ((OracleResultSet)rset).getCLOB(2);

// 아랫부분에 file로 부터 데이타를 읽어 CLOB column에 저장하는
// readFromFile()이 작성되어 있다.

readFromFile(clob);
stmt.execute("commit");

rset = stmt.executeQuery ("select * from test_clob where id=1");

if (rset.next ())
{
clob = ((OracleResultSet)rset).getCLOB(2);
String st = rset.getString(2);

if (clob != null)
System.out.println ("clob length = "+clob.length ());
}

// 아랫부분의 CLOB 컬럼의 데이타를 읽어 다시 다른 file로 write하는
// writeToFile()을 호출한다.

writeToFile(clob);
}

catch (SQLException sqle) {
System.out.println("SQL Exception occured: " + sqle.getMessage());
sqle.printStackTrace();
}

catch(FileNotFoundException e) {
System.out.println("File Not Found");
}

catch (IOException ioe) {
System.out.println("IO Exception" + ioe.getMessage());
}
}

//


// test.txt file을 읽어 test_clob.c column에 저장한다.

static void readFromFile (CLOB clob) throws Exception {
File file = new File("/home/ora920/eykim/test.txt");
FileReader in = new FileReader(file);
Writer out = clob.getCharacterOutputStream();

int chunk = clob.getChunkSize();
System.out.print("The chunk size is " + chunk);
char[] buffer = new char[chunk];
int length;

while ((length = in.read(buffer,0,chunk)) != -1)
out.write(buffer, 0, length);

in.close();
out.close();
}

//------------------------------------------------------------------
// test.clob.c column의 데이타를 읽어 out.txt file로 write한다.

static void writeToFile (CLOB clob) throws Exception {
int chunk = clob.getChunkSize();

int length;
char[] buffer = new char[chunk];
FileWriter outFile = null;
outFile = new FileWriter("/home/ora920/eykim/out.txt");
Reader instream = clob.getCharacterStream();

while ((length = instream.read(buffer)) != -1) {
outFile.write(buffer, 0, length);
}

instream.close();
outFile.close();
}

}


Reference Documents


SCR #998


반응형
반응형

입력되는 테이블을 NoLogging 상태로 만들기

alter table  TFEI_TEMP_SND_RCV_FILE nologging;

append 힌트 사용하기

대용량 데이타를 insert 할 경우는 시간이 매우 많이 걸리게 된다.

 그러다가 temp 사이즈나 데이타 오류로 인해 에러가 나더라도

바로 에러를 밷는것이 아니라 롤백을 모두 한후에야

에러를 나타낸다.
 

총 insert 하는 데 걸리는 시간이 3시간이라면

2시간 진행된 작업이 잘못 됐다는걸 알았다(또는 에러가 났다는걸 알았다)

 

그러면 바로 에러를 뱉어내는 것이 아니라 롤백을 2시간 해주어야 된다

즉..  잘못된 insert 작업을 2시간 하다가 취소하면 2시간 기다려야(롤백하느라) 된다는 것이다..


 

얼마나 짜증나는 일인가???
 

해답이 있다 APPEND 를 쓰면 된다.

 

insert /*+append*/ into aaa

select * from ......



 

append 힌트는 롤백을 쌓지않고 바로 테이블스페이스에 저장하게 된다.

취소할 경우에는 그동안 저장된 데이타만 날리기때문에 취소도 즉시 된다.

 

정말 빠르다~~


 

하지만 단점이 있으니....


 

롤백을 쌓는 insert 의 경우에는 얼마나 작업이 진행됐는지 롤백 세그먼트 크기를

보면서 모니터를 할 수 있다.


 

하지만 append 는 롤백을 쌓지 않기 때문에 얼마나 진행됐는지 확인하기가 쉽지 않다.


 

한가지 힌트가 있다면

insert 되는

테이블의 크기라 1024M 이고 익스텐트를 128M이라면

insert 되는 데이타가 1024M의 용량을 넘었다면 익스텐트를 일으키기 때문에

extend 를 하는지 안하는지를 보면 작업이 어느정도 진행되는지 알수 있다.

 

출처 : 일부 나... 그외

http://shinyoung.kr/514

또한 프로세스 개수가 넉넉하다면 PARALLEL 옵션을 주면 더욱 좋다 ㅋ

반응형
반응형

rem -----------------------------------------------------------------------
rem Filename:   bulkbind.sql
rem Purpose:    Simple program to demonstrate BULK COLLECT and BULK BIND.
rem Notes:      Bulk operations on ROWTYPE only work from and above.
rem Date:       12-Feb-2004
rem Author:     Frank Naude, Oracle FAQ
rem -----------------------------------------------------------------------
set serveroutput on size 50000

DECLARE
  CURSOR emp_cur IS SELECT * FROM EMP;

  TYPE emp_tab_t IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER;
  emp_tab emp_tab_t;            -- In-memory table

  rows NATURAL        := 10000;   -- Number of rows to process at a time
  i    BINARY_INTEGER := 0;
BEGIN
  OPEN emp_cur;
  LOOP
    -- Bulk collect data into memory table - X rows at a time
    FETCH emp_cur BULK COLLECT INTO emp_tab LIMIT rows;
    EXIT WHEN emp_tab.COUNT = 0;

    DBMS_OUTPUT.PUT_LINE( TO_CHAR(emp_tab.COUNT)|| ' rows bulk fetched.');

    FOR i IN emp_tab.FIRST .. emp_tab.LAST loop
      -- Manipumate data in the memory table...
      dbms_output.put_line('i = '||i||', EmpName='||emp_tab(i).ename);
    END LOOP;

    -- Bulk bind of data in memory table...
    FORALL i in emp_tab.FIRST..emp_tab.LAST
      INSERT /*+APPEND*/ INTO emp2 VALUES emp_tab(i);

  END LOOP;
  CLOSE emp_cur;
END;
/

 

/*

 bulk collection 관련 예제

출처 : http://hany4u.blogspot.com/2008/11/bulk-collect-and-bulk-bind.html

*/

반응형

+ Recent posts