코딩을 하다보면 다음과 같은 에러가 나는 경우가 정말 간혹 한번쯤 있다.


ORA-01460: 요구된 변환은 실행될 수 없습니다.


보통 CLOB를 사용하면서 VARCHAR2와 변경 문제 때문에도 나는 경우가 있지만, 특별히 CLOB를 사용하지 않은 경우에


VARCHAR2에 입력된 값의 byte를 봐야 한다. VARCHAR2는 4000 byte 이상 입력하지 못하므로... (결국 3999 byte에서 끊어줘야 하는 문제)


Java 로직부에서 String에 4000 byte 이상을 전달하고 쿼리에서 VARCHAR2인 타입의 변수에 넣으려다보니 생기는 문제...

'데이터베이스 > Oracle' 카테고리의 다른 글

TEMPORARY TABLE  (0) 2015.09.25
ORA-12899: value too large for column  (0) 2015.09.24

< Temporary Table >


하나의 세션 동안이나 트랜젝션(Commit 하기 전) 동안 임시적으로 데이터를 보관하기 위해 제공된다. (세션이나 트랜젝션이 종료되면 테이블의 데이터는 Truncate 된다.

일반테이블과 다르게 테이블의 레이아웃은 dictionary에 존재하지만 데이터는 디스크 상에 존재하지 않고

메모리상에서 [INSERT] [UPDATE] [DELETE] [SELECT] 하는 테이블이다.


1. TEMPORARY TABLE 생성


CREATE GLOBAL TEMPORARY TABLE [테이블명]

      ON COMMIT [DELETE|PRESERVE] ROWS ;

ON COMMIT PRESERVE ROWS : 세션별로 데이터가 존재 (세션이 종료시 데이터 소실)

ON COMMIT DELETE ROWS    : 트랜젝션별로 데이터 존재  (Commit 하면 데이터 소실)


2. 예제


-- Session-Level Temporary

CREATE GLOBAL TEMPORARY TABLE TBL1

(

    ID       NUMBER

,   NM      VARCHAR2(10)

,   DT      DATE

)     ON COMMIT PRESERVE ROWS ;


-- Transaction-Level Temporary

CREATE GLOBAL TEMPORARY TABLE TBL2

(

    ID        NUMBER

,   NM       VARCHAR2(10)

,   DT       DATE

)      ON COMMIT DELETE ROWS ;


SQL>

SELECT TABLE_NAME

     , DURATION

  FROM USER_TABLES

 WHERE TEMPORARY   = 'Y'

   AND TABLE_NAME IN ('TBL1', 'TBL2') ;

TABLE_NAME | DURATION

------------------------------

TBL1       | SYS$SESSION

TBL2       | SYS$TRANSACTION

SYS$SESSION        : 세션이 종료되면 데이터 소실

SYS$TRANSACTION : 트랜젝션이 종료되면 데이터 소실


-- 하나의 임시 테이블은 더로 다른 사용자가 접근이 가능하다. 하지만 데이터는 서로 다르다.

-- 자신의 SID를 조회

SQL> SELECT SID FROM V$MYSTAT WHERE ROWNUM = 1 ;

       SID

----------

       962


-- 데이터 INSERT

SQL> INSERT INTO TBL1(ID, NM, DT) VALUES(1, '홍길동', SYSDATE) ;


-- 데이터 SELECT (이때 다른 세션에서 조회하면 데이터가 존재하지 않는다.)

SQL> SELECT * FROM TBL1 ;

ID  | NM       | SYSDATE

-------------------------------------

1   | 홍길동   | 2015/09/25 10:52:04


-- 트랜젝션으로 설정한 경우 Commit시 데이터가 사라짐

-- 다른 사용자가 접속한 경우도 데이터는 보이지 않는다.

SQL> COMMIT ;


-- 세션으로 설정한 경우 Exit하는 경우 데이터가 사라짐

-- 다른 세션으로 접속한 경우도 데이터는 보이지 않는다.

SQL> EXIT


==> TEMP TABLE도 일반 TABLE처럼 Insert or Update  할 때 Lock잡는다. Lock조회하면 조회된다


* 중요

 테이블의 Definition 은 Dictionary 에 저장된다.

 하지만 SELECT TABLESPACE_NAME FROM DBA_TABLES ; 를 조회해 보면 조회되지 않는다.

 테이블의 정보는 Dictionary (owner의 DEFAULT_TABLESPACE)에 저장되지만 실 데이터는 디스크에 저장되지 않고 메모리상에서 소멸되기 때문이다.


3. TEMPORARY TABLE 삭제


DROP TABLE T1 ;

DROP TABLE T2 ;



ORA-12899: value too large for column


( ORA-12899: "유저명"."테이블명"."컬럼명" 열에 대한 값이 너무 큼(실제: m, 최대값: n)  )


ORA-12899는 INSERT를 한다거나 UPDATE를 하다가 다음과 같은 에러가 발생하는 경우가 있다.


1. 실제로 최대값보다 실제 입력된 값이 커서 발생하는 경우이다.


2. 오라클의 문자셋 NLS_CHARACTERSET의 설정의 문제다 ( 캐릭터셋(charset)의 문제 -> UTF-8 과 ASCII의 Byte 수가 달라 각 3Byte, 2Byte, 1Byte를 계산하다 문제가 생긴 경우)



이번에 포스팅 할 경우는 공백이다.


쉽게 발생하는 케이스가 아니라서,


보통 위의 경우라면 해결방법이 인터넷에 많이 올라와있지만 공백의 경우 찾기도 쉽지 않고 설마 공백이 문제가 될 거라 생각하지 않았다.


대부분 실제 입력 값이 크지 않고 입력되는 값이 모두 영어인 경우라면 다음을 확인해보면 될 것 같다.


3. 공백값 chr(49824)


오라클 공백값이 기존 1byte의 스페이스 키를 입력하여 나온 chr(32) 이다.


하지만 에러가 나는 공백값은 아닌 chr(49824)는 2Byte이다. (공백인듯 공백아닌 공백같은)


두 공백을 비교하면


 chr(32)

 chr(49824)

 1Byte

 trim가능, replace 처리가 스페이스 키로 만든 공백으로 처리 가능

 2Byte 

 trim불가, replace 처리가 스페이스 키로 만든 공백으로는 불가능


가장 쉽게 해결하는 방법은 해당 공백을 복사하여 replace해주는 방법이다.


SELECT REPLACE(CHR(49824), ' ', ' ') FROM DUAL;


이 공백문자를 만들기도 힘든데 어떻게 들어왔는지는 모르겠다.

'데이터베이스 > Oracle' 카테고리의 다른 글

ORA-01460: unimplemented or unreasonable conversion requested  (0) 2015.10.19
TEMPORARY TABLE  (0) 2015.09.25

+ Recent posts