반응형

Oracle 로고

이번에 개발 서버에서 작업했던 DB 작업들을 운영 서버에 반영하는 기간이 있었다. 그 때, 테이블의 컬럼들을 추가를 하고 있었는데, 운영 파트에서 에러가 발생했다. 확인을 해보니, 내가 새로 넣은 컬럼에서 NULL 에러가 발생했는데, 내가 넣은 모든 컬럼에 대해서는 NOT NULL로 컬럼들을 생성하였으나, 다른 문제로 에러가 발생한 것으로 확인됐다. 이 사건을 계기로 NOT NULL과 DEFAULT에 대한 관계에 대해 상기하기 위해 다시 기록한다.


목차

0. 테스트를 위한 테이블 생성
1. NOT NULL 제약 조건
2. DEFAULT 제약 조건
3. NOT NULL과 DEFAULT의 제약 조건
4. 결론

0. 테스트를 위한 테이블 생성

가장 먼저, NOT NULL과 DEFAULT의 제약 조건에 대한 관계를 알아보려면 직접 경험해 보는게 가장 좋다.

 

1) 테이블 생성

간단하게 TESTT라는 테이블을 만들었고, 그 안에 NAME, NAME02, NAME03이라는 컬럼을 만들었는데, NAME은 VARCHAR2(20) 타입에 DEFAULT는 ' ', NOT NULL 설정을 줬고, NAME03에는 DEFAULT만 ' '공백을 줬다.. 테스트를 하기 위한 테이블은 만들어 졌으니, 이제 직접 경험을 해야 한다.

CREATE TABLE "CODING"."TESTT" (	
	"NAME" VARCHAR2(20) DEFAULT '  ' NOT NULL ENABLE
	"NAME02" VARCHAR2(100) DEFAULT ' ' NOT NULL;
	"NAME03" VARCHAR2(100) DEFAULT ' ' NULL;
)

 

1. NOT NULL 제약 조건

이제 TESTT 테이블에 NAME이라는 컬럼에 데이터를 넣어 보자.

INSERT INTO TESTT (NAME) VALUES('');

 

위와 같이, 쿼리를 실행하면 과연 데이터가 들어갈까?

SQL Error [1400] [23000]: ORA-01400: NULL을 ("CODING"."TESTT"."NAME") 안에 삽입할 수 없습니다

바로 NULL을 삽입할 수 없다고 나온다. 즉, NAME의 컬럼은 NOT NULL로 체크가 되어 있다. NULL이 들어올 경우에는 제약 조건에 걸려 오류를 발생한다. 그러면 여기서 값을 넣지 않는다면 어떻게 될까?

 

INSERT INTO TESTT (NAME) VALUES();

원래는 값이 들어오지 않은 경우로 되어 DEFAULT값이 들어가야 하지만, 현재 DBeaver에서는 누락된 표현식이라면서 에러가 발생한다.

 

즉, NOT NULL 제약 조건은 값을 넣지 않거나 NULL이 들어갔을 경우 제약 조건에 걸린다.(원래는 값을 넣지 않으면 DEFAULT 값이 들어가는 걸로 알고 있는데, 직접 DBeaver 툴에서 오라클로 실행하니 누락된 표현식이라고 나온다.)

 

2. DEFAULT  제약 조건

DEFAULT의 제약 조건은 값이 들어오지 않은 경우에는 DEFAULT로 특정 값을 넣는다라는 제약 조건이다.

예시를 보자.

 

"NAME03" VARCHAR2(100) DEFAULT ' ' NULL;
INSERT INTO TESTT (NAME03) VALUES();

위와 같이 실행하면 어떻게 될까?

 

DEFAULT 제약 조건에 걸리지 않고 DEFAULT값이 들어가는게 맞다.

근데, DBeaver 오라클에서는 NULL로 들어간다.

 

그래서, NULL인 데이터만 WHERE 조건을 걸어서 가져오면 그 값을 가져온다.

SELECT *
  FROM TESTT
 WHERE NAME03 IS NULL;

 

진짜로 NULL이 들어 간다..?

 

3. NOT NULL과 DEFAULT의 제약 조건

여기서 이제, NAME이라는 컬럼에 대해선 NOT NULL과 DEFAULT를 설정했다.

"NAME" VARCHAR2(20) DEFAULT '  ' NOT NULL ENABLE

즉, NULL이 들어오는 경우에는 NOT NULL의 제약 조건에 걸리면서, 값이 들어오지 않은 경우에는 DEFAULT로 ' ' 공백이 들어간다는 말이다.

 

INSERT INTO TESTT (NAME) VALUES();

위의 쿼리를 실행하면 누락된 표현식으로 에러가 발생한다.

 

INSERT INTO TESTT (NAME) VALUES('');

위의 값도 NULL로 판단되어 NOT NULL 제약 조건에 걸린다.

 

위의 테이블에서 컬럼은 NAME, NAME02, NAME03으로 구성되어 있다. 여기서, NAME03에 데이터만 넣을 경우에는 다른 컬럼들은 DEFAULT가 작동한다. 이게, 명시를 하지 않으면 DEFAULT가 작동을 하고, 명시를 하게 된다면 꼭 값을 넣게 되어 있나 보다.

INSERT INTO TESTT (NAME, NAME02, NAME03) VALUES (, , 1);

위와 같이, 실행하면 누락된 표현식이라고 에러가 발생하고, 아래와 같이 하면 NAME과 NAME02에 DEFAULT가 작동하여 공백이 들어간다.

INSERT INTO TESTT (NAME03) VALUES (1);

 

4. 결론

자 결론입니다.

결론은 그냥 NULL을 허용하지 않고 DEFAULT를 설정하여 문자열이면 공백을 넣고, 숫자면 0을 넣어서 관리하는 것이 좋습니다. NULL을 허용해 버리면 그 때부터 관리하기가 정말 어려워 집니다.

 

예시 1.

예를 들어서, 상태에 대한 NULL을 허용한다고 합시다. 상태에 대한 FLAG는 정상, 에러, 경고가 있는데 NULL이 허용 되면 총 4개의 FLAG 상태가 생깁니다. 그러면, 조회를 할 때에도 NULL 체크를 해야 하고 데이터를 가져올 때 NULL이 있으면 NULL에 대한 EXCEPTION도 발생하여 예외처리도 해야 하기 때문에 로직이 더 길어지게 됩니다.

 

예시 2.

또한, 오라클의 경우에는 NULL 체크를 하려면 비교 연산자를 사용할 수 없습니다. IS NULL, IS NOT NULL 조건을 사용하여 조건을 걸어야 합니다. 그러면, 모든 쿼리를 생성할 때 IS NULL, IS NOT NULL 조건을 계속해서 넣어야 하기 때문에 쿼리의 복잡도가 증가합니다.

 

예시 3.

그리고, NULL을 사용해서 백엔드 단으로 문자열 데이터를 가져올 경우에는 "NULL".equals(문자열 변수) 이런식으로 체크해야 하는 번거로움이 있어 코드가 증가합니다.

 

이렇기 때문에 저는 모든 컬럼에 대해서 NULL을 허용하지 않고 DEFAULT 값을 주어 관리를 합니다.

 


 

 

반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기