오라클 호환성 기능은 DB2_COMPATIBILITY_VECTOR 레지스트리 변수에 값을 적용함으로서 오라클 문법/표현등을 사용하게 된다.

그러나 일부 기능은 데이터베이스를 생성하기 전에만 적용되는 것들이 있다.

Developerworks에 나온 문서(https://www.ibm.com/developerworks/mydeveloperworks/blogs/SQLTips4DB2LUW/entry/about_the_db2_compatibility_vector_and_what_not_to_say_at_the_dinner_table282?lang=en) 의 내용 및 기억을 더듬어보면

1. NUMBER

2. VARCHAR2

3. DATE

4. Oracle Data Dictionary

정도가 아닌가 싶다.

 

이 중 VARCHAR2를 세부적으로 들여다보면 특별한 기능을 포함하고 있다.

오라클이 공백과 NULL 값 구분을 하지 않기 때문에, DB2로 Data Migration을 하게 되면 이것은 문제가 된다. (DB2는 공백과 NULL을 구분하기에)

 

따라서 SQL 내에서 공백의 데이터를 처리하다보면 Oracle과는 다른 결과를 갖게 된다.

이 문제를 해결하기 위해서 VARCHAR2 (0x20) 값을 적용할 필요가 생긴다.

 

1. DB2에서 공백 값 테스트

$ db2 "values (COALESCE('','NULL'))"

1
----


$ db2 "values (COALESCE(' ','NULL'))"

1
----


$ db2 "values (COALESCE(NULL,'NULL'))"

1
----
NULL



$> db2 "values (bigint(''))"

1
--------------------


SQL0420N  Invalid character found in a character string argument of the function "BIGINT".  SQLSTATE=22018

 

2. 오라클의 공백 값 테스트

SQL> select nvl('','NULL') as C1 from dual;

C1
----
NULL


SQL> select nvl(' ','NULL') as C2 from dual;

C
-


SQL> select nvl(NULL,'NULL') as C3 from dual;

C3
----
NULL



SQL> select to_number('') as C4 from dual;

        C4
----------

 

4번째 SQL을 통하여 DB2에서는 “공백 값"이 숫자로 캐스팅되지 못하고 SQL0420N 오류가 발생했다.

 

오라클 호환성 (db2set DB2_COMPATIBILITY_VECTOR=20) 을 적용해도 “공백"값은 숫자형으로 형 변환되지 못한다.

 

이 경우 오라클처럼 “공백" 값을  숫자로 형변환 되도록 하기 위해서는 db2set DB2_COMPATIBILITY_VECTOR=20 를 적용하고 DB 재생성을 해야 된다.

$> db2set -all
[i] DB2_COMPATIBILITY_VECTOR=20

$> db2 drop db sample
$> db2stop
$> db2start
$> db2sampl
$> db2 connect to sample
$> db2 "values (bigint(''))"

1
--------------------
                   -

 

위 문제는 사전 테스트를 통하여 “공백"처리 문제가 발생함을 확인하는 경우 VARCHAR2 호환성을 적용되어야 할 것이다.

그렇지 않다면 SQL 수정이 되어야 할 것이다.

 

다른 관점에서는 “해당 DB가 오라클 호환성을 적용하고 생성된 DB인지” 확인하는 방법이 될 수도 있다.

예를 들어 DB2 구성 작업에 많은 수의 인스턴스 및 DB 생성 작업 시,  “오라클 호환성"을 적용하고 DB가 만들어져야 되는 상황이라면

오라클 호환성이 제대로 적용되어 생성된 것인지 확인하고 싶을 수 있다.

- 많은 반복 작업으로 작업 검증 절차를 빠뜨리거나

- 인스턴스 구성 후 자동으로 인스턴스가 실행 중인 상황에서, 호환성 적용하고 (인스턴스 재시작 없이) DB를 생성된 것은 아닌지

- 이미 구축된 DB2 환경에 (히스토리 없이 지원을 하게 되어) 오라클 호환성 관련된 문제가 발생한 경우 호환성 적용 시점이 언제인지 확인할 때

오라클 포팅작업을 하다보니 오라클 호환성 기능에 대해 새롭게 살펴보게 되는 것 같다.

오라클에서는 숫자형으로 선언된 컬럼에 공백값(‘’)을 입력하면 NULL 값 처리가 된다. DB2에서는 공백값을 입력하면 형 변환 오류가 발생하여 입력이 실패한다. 만일 문자열로 된 숫자 값 (예: ‘1234’) 식의 값을 입력하면 자동 캐스팅 되어 입력된다.

 

iBatis에 대해서는 잘 모르지만, DBMS Migration 작업을 하다보면 XML 문서에 SQL문들을 모아 놓고 dynamic 하게 SQL을 실행하는 환경을 보게 된다. 아마도 XML문서에 값들도 동적으로 받아 처리되도록 하다보니, 매개변수의 데이터 유형이 DB에 선언된 컬럼 유형과는 다르게 지정되는 경우가 많다. (아마도 개발편의성 때문에 대부분은 VARCHAR로 일괄 선언하는 경우가 많지 않을까 싶다.)

 

이렇게 되다 보니 숫자형으로 선언된 컬럼에 문자열 값이 입력이 되다보니 DB2에서는 자동으로 형 변환을 못하고 에러를 반환하는 경우가 많다. (V9.5 이후로 오라클 호환성 기능이 나오면서 자동형변환 처리는 많이 편해진 편이다.)

 

오라클처럼 공백값(‘’)을 NULL 값으로 처리하도록 하기 위해서는 호환성 벡터 0x20 값이 적용되어야 하며, 적용 후 DB 생성 작업을 해야 된다.

참고로 DB2 정보센터 문서에는 “호환성 벡터”를 적용하는 경우 DB locale은 유니코드(utf-8)을 사용할 것을 권고하고 있다.

또한 DB2 DeveloperWorks 기술문서에 VARCHAR2 (0x20) 값은 위험할 수 있다고 권고되는 값이니 업무 상 필요한 경우에만 사용하도록 주의해야 한다.

 

공백(‘’) 테스트 (오라클)

SQL> create table t1 (c1 integer, c2 integer);
SQL> insert into t1 values (1,'');
SQL> insert into t1 values (2,'   ');
         ORA-01722:
SQL> insert into t1 values (3,NULL);

SQL> select * from t1;

        C1         C2
---------- ----------
         1
         3

 

 

공백(‘’) 테스트 (DB2 – 호환성 적용 전)

db2 "create table t1(c1 int, c2 int)"
db2 “insert into t1 values (1,'')

SQL0420N  함수 "INTEGER"의 문자열 인수에 유효하지 않은 문자가 있습니다.

db2 “insert into t1 values (2,'   ')

SQL0420N  함수 "INTEGER"의 문자열 인수에 유효하지 않은 문자가 있습니다.


db2 "insert into t1 values (3,'1234')"
DB20000I  The SQL command completed successfully.

db2 "insert into t1 values (4,NULL)"
DB20000I  The SQL command completed successfully.

db2 "select * from t1"

C1          C2
----------- -----------
          3        1234
          4           -

  2 record(s) selected.


 

공백(‘’) 테스트 (DB2 – 호환성 적용 후)

db2set DB2_COMPATIBILITY_VECTOR=20
db2stop force
db2start
db2 create db test
db2 connect to test
db2 "create table t1(c1 int, c2 int)"
db2 “insert into t1 values (1,'')
DB20000I  The SQL command completed successfully.

db2 "insert into t1 values (2,'   ')"

SQL0420N  Invalid character found in a character string argument of the function "INTEGER".

 

db2 "select * from t1"

C1          C2
----------- -----------
          1           -

  1 record(s) selected.

 

참고로 0x20 값 적용하고 DB 생성 후, 0x20 값을 제거해도 공백(‘’)은 NULL 값으로 인식된다.

 

참고

1) developerWorks 오라클 호환성 기술문서

https://www.ibm.com/developerworks/mydeveloperworks/blogs/SQLTips4DB2LUW/entry/about_the_db2_compatibility_vector_and_what_not_to_say_at_the_dinner_table282?lang=en

 

2) 호환성 벡터 값

http://pic.dhe.ibm.com/infocenter/db2luw/v10r1/index.jsp?topic=%2Fcom.ibm.db2.luw.apdv.porting.doc%2Fdoc%2Fr0052867.html

+ Recent posts