오라클 트리거를 애플리케이션층에서 손댈 일은 거의 없지만, 오라클을 타겟으로 테스트를 할 경우 테이블을 일괄 생성, 삭제할때 트리거도 생성, 삭제를 반복해야할 때가 있다.

보통 JUnit 을 이용해서 데이터 베이스를 테스트할 때 다음과 같은 전처리 후처리를 시행하게 된다.

1. 테이블 생성 쿼리를 실행 (create table, create sequence, crate trigger)
2. 테이블에 샘플 데이터들을 입력 ( insert into ... )
3. 테스트 메소드 실행 ( test_insert_new_place() )
4. 테이블 일괄 drop ( drop table, drop sequence, drop triggr .. )

1, 2 번을 setUp(); 에서 실행하고 4번을 tearDown(); 에서 실행하면 각각의 테스트에서 데이터 베이스를 조작 변경하더라도 데이터 베이스의 상태를 일관되게 유지할 수 있다. 이를 위해서 create.sql, trigger.sql, sample.sql, drop.sql 과 같이 파일을 따로 만들어두고 테스트를 하면 편리한데 테스트 과정에서 만들어진 create.sql, trigger.sql 은 그대로 가져다가 애플리케이션 배포 시에 사용하면 된다.

그런데 윈도우 환경에서 trigger.sql 파일 안에 트리거 관련 쿼리를 정의했을 경우 각각의 쿼리를 읽어들인 후 DDL 문으로 실행하면 아무런 에러도 없이 트리거가 잘 만들어진 듯 하나 , 실제 트리거가 촉발될 때 실패할 때가 있다.

아래는 Places 테이블에서 특정 place를 삭제할 때 삭제할 place의 ID 를 foreign key로 참조하는 거래(Transactions) 들이 기본값인 1(장소 없음)을 참조하게 바꿔주는 트리거이다. 오라클에서는 on delete set default 의 기능이 없기 때문에 아래와 같은 트리거를 정의해서 삭제 전에 참조를 모두 제거해주면 된다.


그런데 위 쿼리를 읽어들여서 실행하면 아래와 같이 ORA-04098 예외가 발생하며 트리거가 실패한다.
문제는 파일에서 쿼리를 읽어들일때 문자열에 포함된 CARRIAGE RETURN (CR ) 때문에 발생하는 것으로 보인다.
아래와 같이 쿼리에서 CR을 제거하면 트리거가 제대로 실행된다.
윈도우에서는 줄바꿈 표시를 CRLF(0xDA) '\r\n' 으로 나타내는데, 위와같이 여러줄에 걸쳐서 하나의 트리거를 정의하면 중간에 들어있는 '\r'이 문제를 일으키는 것으로 보인다.

UNIX와 같이 LF(0xA) '\n' 만으로 줄바꿈을 표시하는 운영체제에서는 문제가 없을 것 같은데, 테스트는 해보지 않아서 확실하게 말은 못하겠다.

특이한건 create table, create sequence 와 같은 DDL 문장은 아무 문제가 없는데 트리거에서만 '\r'이 문제를 일으킨다. 위와같이 \r을 공백으로 바꿔서 문제를 해결하긴 했지만 아무튼 오라클 jdbc 구현체는 희한한 행동을 보여줄때가 많다는거. -_-;
Posted by yeori
,