[ ORACLE에서의 자료형 VARCHAR2, CLOB 사용 및 가공시 주의점 ]

보통 4000bytes 이하의 문자열에 사용되는 VARCHAR2

대용량 데이터 LOB 의 문자자료형인 CLOB 데이터

 

 

[ Charset 에 따른 한글 문자 bytes 크기 ]

ORACLE 의 권장 character set 은 UTF-8 이며, UTF-8 은 문자 하나에 최대 4bytes.

* 한글은 UTF-8 에서 문자 하나당 3bytes, EUC-KR 에서 문자 하나당 2bytes

* SQL에서 VARCHAR2 는 최대 4000bytes 길이 제한.

 

※ DB charset 확인하는 방법

1) 설정확인(권장)

SELECT name, value$
FROM sys.props$
WHERE name = 'NLS_CHARACTERSET';

2) 문자를 조회하여 확인

SELECT LENGTHB('일') FROM DUAL;

결과로 리턴되는 BYTES 크기 확인

* LENGTHB 는 BYTES 크기 반환

 

아래와 같이 TABLE 생성시 

CREATE TABLE sample.persons(
    name VARCHAR2(9) NOT NULL,
    PRIMARY KEY(name)
);

VARCHAR2(9) 의 9은 bytes 를 의미하며 UTF-8 기준으로 한글은 3글자밖에 들어갈 수 없다.

 

 

[ VARCHAR2 칼럼에 데이터 넣기 ]

1. Query 에서 잘라 넣기

1) SUBSTR 사용하여 CHAR 문자 잘라 넣기

INSERT INTO persons VALUES (SUBSTR('네자이름'), 1, 3));

* SUBSTR 은 문자 length 를 기준으로 자름

* TABLE DESC 에 명시된 자료형의 크기는 default가 bytes 기준이므로 CHAR length를 기준으로 위와 같이 문자열을 잘라넣는건 부적절.

 

2) SUBSTRB 사용하여 BYTES 단위로 문자 잘라 넣기

INSERT INTO persons VALUES (SUBSTRB('네자이름'), 1, 9));

* SUBSTRB 는 문자 bytes 를 기준으로 자름

* 위와같이 데이터를 넣을 경우 bytes단위로 문자열이 잘려나가기 때문에 한글이 깨질 수 있으므로 부적절.

 

※ 또 다른 문제.

SQL에서 VARCHAR2 는 최대 4000bytes 길이 제한이 있어

1), 2) 에서 사용된 SUBSTR, SUBSTRB 함수 모두 input 값이 4000bytes 가 넘을시 "ORA-01704: 문자열이 너무 깁니다" 에러가 발생한다.

 

2. 소스레벨에서 BYTES 단위로 잘라 넣기

정해진 bytes 크기의 한도내에서 한글이 깨지지 않게 문자열 자르기

SQL 에서 문자열을 가공하기보단 소스레벨에서 가공

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static String subStrByte(String str, int cutlen){
        if(!str.isEmpty()){
            str = str.trim();
            if(str.getBytes().length <= cutlen) {
                return str;
            }else{
                StringBuffer sbStr = new StringBuffer(cutlen);
                int nCnt = 0;
                for(char ch: str.toCharArray()){
                    nCnt += String.valueOf(ch).getBytes().length;
                    if(nCnt > cutlen) break;
                    sbStr.append(ch);
                }
                return sbStr.toString();
            }
        } else {
            return "";
        }
    }
cs

 

[ CLOB 데이터 읽기 및 가공하기 ]

CLOB 데이터는 LENGTH, LENGTHB, SUBSTRB 함수 등을 지원하지 않음.

 

VARCHAR2 데이터에서 사용가능한 함수 사용을 위해 VARCHAR2 로 변환하고자 할 경우,

DBMS_LOB.SUBSTR(clob칼럼, 가져올길이, offset)을 사용하여 VARCHAR2 로 변환이 가능

* CLOB 데이터 가공시 SUBSTR 보다 DBMS_LOB.SUBSTR 의 퍼포먼스가 뛰어남 (참고)

* DBMS_LOB.SUBSTR() 사용시에도 4000bytes 를 넘는 데이터를 가져오지 않도록 주의 해야한다

 

※ 또 다른 문제.

temp segment 가 unrelease 되는 현상.

CLOB 칼럼에 함수를 직접 사용할 경우, 메모리와 같은 역할을 하는 temp segment를 사용하게 되며 release 하지 않고 쌓일 수 있다. 이는 서버 장애를 유발하여 서비스 전체에 영향을 줄 수 있다.

실제로 이와 관련하여, 운영중인 DB서버 전체가 마비되어 서비스 장애를 경험해 보았다..

=> CLOB 칼럼에 함수 사용은 지양하자. 소스레벨에 그대로 가져와서 소스레벨에서 자르는 걸 권장.

 

[ 관련에러 ]

ORA-01704: 문자열이 너무 깁니다

ORA-64203: 문자 집합 변환 후 대상 버퍼가 너무 작아 CLOB 데이터를 보유할 수 없습니다.

ORA-06502: 문자열 버퍼가 너무 작습니다.

 

참고 :

https://tomining.tistory.com/95

 

 

반응형

'DB > ORACLE' 카테고리의 다른 글

[ORACLE] CLOB BLOB  (0) 2021.04.14
[ORACLE] 실행중인 쿼리 조회  (0) 2021.03.25
ORACLE 로컬 bit 확인  (0) 2021.03.16
[oracle] sysdate  (0) 2021.02.08
LEAD, LAG  (0) 2021.02.03

+ Recent posts