출처 :자바 서비스넷
ref :
http://www.javaservice.net/~java/bbs/read.cgi?m=devtip&b=jdbc&c=r_p&n=1152605190

Oracle의 varchar2 타입에서 입력 가능한 최대 크기는 4KB. 영문은 4천자, 한글은 2천자...

문자열의 길이를 byte 로 계산하기 때문에 한글과 같이 문자당 2바이트 이상을 사용하는 경우 입력할 수 있는 문자의 개수가 줄어드는데 서 문제가 발생. 위 기준대로라면 한글은 2천자가 들어가야 하나, 사실은 그보다 훨씬 적게 들어가는 상황이 발생함.

PreparedStatement 인스턴스에서 setString() 으로 문자열을 지정할 경우에 그러한데, 내부적으로 문자를 UTF-8로 변환해서 길이가 4KB를 넘는지 보게됨. 영문의 경우 2바이트로 계산해서 최대 2천자까지 들어가나, 한글의 경우 UTF-8에서 문자당 3바이트(?)를 차지하므로 입력 가능한 문자의 개수는 666자(1998 바이트)에 불과함.

하지만 Statement 로 할 경우에 이런 제약은 없으나, 쿼리가 외부에 노출되는 보안상의 문제때문에 기를 쓰고 PreparedStatement 를 사용하려하는 상황임.

해결책은 setString() 이 아니라 setCharacterStream을 사용하면 됨. 이렇게하면 한글 2천자를 넣을 수 있음.

ref : http://blog.naver.com/rockmg?Redirect=Log&logNo=90008680601
ref :
http://apmtip.com/board/zboard.php?id=mysql&no=79

varchar2(4000) 인 칼럼에 영문 4000자 와 한글 2000 자를 입력하는 테스트를 했습니다.

결론부터 얘기하면 Statement 를 사용하면 영문은 4000자, 한글은 2000 자가 입력됩니다.
PreparedStatement를 사용하면 영문은 2000(2000 Byte)자가 입력되고 한글은 666(1332 Byte, UTF-8 : 1998 Byte)자까지만 입력됩니다.(pstmt.setString(1,buffer1.toString())을 사용했을때)

그 이유를 찾아본 결과 버그라고 밖에 생각이 안든다는 게 대다수의 의견이였다.

그러나 내부적으로 jdbc 드라이버에서 UTF-8로 치환해서 길이 비교를 합니다.

그게 2000까지만 인정하더군요.

이에 대한 해결책은 PreparedStatement 에서 영문 4000자, 한글 2000자까지 입력하려면 다음과 같이  pstmt.setCharacterStream() 메써드를 사용하면 됩니다.

     StringReader is = new StringReader(buffer1.toString());
     pstmt.setCharacterStream(1, is, buffer1.toString().length());

그러나 pstmt.setCharacterStream는 한 쿼리에서 두번 이상 쓸수 없는것으로 규정하는듯 하다.

쓰더라도 값이 뒤바뀌거나 문제가 생깁니다.

이유는 Table에 Long 타입은 오직 하나만 가능합니다.

그거에 의거하여 만들어지다 보니 저런 버그가 있습니다.

아니면 아예 Statement를 사용해서 해결합니다.

따라서 DB Table 안에 영문 2000자, 한글 666자 이상 되는 컬럼은 long Type으로 바꾸거나 이러한 길이가 두개 이상일 경우 Statement를 사용해야 합니다.

 

ref : http://www.jee1.name/blog/186?TSSESSION=40ea754930d07fc940a26c7c2b2bdf9f

ORACLE DB에 긴문장 삽입시...

출처 : 까오기네 집
오라클에서 varchar2(4000)으로 타입을 정하고 PreparedStatement 로 인서트를 하면 1600자도 안 들어 갑니다.
Statement 로 하면 다 들어 가고여... 하지만 보안상 Statement 사용 하기는 뭐하져.


    StringReader contentreader = new StringReader(content);
    ...
    ...
    ...
    pstmt.setCharacterStream(1,contentreader,content.getBytes().length);


이렇게 long type 입력하드시 하면 4000 byte 다 쓸 수 있습니다.

EX)

Connection conn = null;
PreparedStatement pstmt = null;
StringBuffer query = new StringBuffer();
query.append(" insert into ").append(" EVENT_LOTTORY_LOG ").append(
       " (CUST_SEQ,EDATE,ETIME,EPATH,CONTENT) ").append(" values(?,?,?,?,?)");
DbConnect dbCon = new DbConnect();
try {
   StringReader contentreader = new StringReader(content);
   conn = dbCon.getConnection();
   pstmt = conn.prepareStatement(query.toString());
   pstmt.setString(++index, cust_seq);
   pstmt.setString(++index, W3sliUtil.getToday("yyyyMMdd"));
   pstmt.setString(++index, W3sliUtil.getToday("HHmm"));
   pstmt.setString(++index, path);
   pstmt.setCharacterStream(++index, contentreader,content.getBytes().length);
   pstmt.executeUpdate();
   return true;
} catch (Exception e) {
   e.printStackTrace();
   return false;
} finally {
   dbCon.release(pstmt);
   dbCon.release(conn);
}

Posted by yeori

댓글을 달아 주세요

  1. 2011.01.05 11:53 신고

    유용한 정보 감사합니다. 좀 담아갈게요 :)

나의이름 패스워드

홈페이지 비밀글