ORA-01400 cannot insert NULL — NOT NULL 제약 위반 에러 원인·해결·예방
Oracle Database에서 INSERT나 UPDATE를 실행하다가 ORA-01400: cannot insert NULL into ("스키마"."테이블"."컬럼") 에러를 만나는 경우가 있다. NOT NULL 제약이 걸린 컬럼에 NULL을 넣으려고 시도할 때 발생하는 에러로, 단순 명시적 NULL 입력뿐 아니라 INSERT 컬럼 목록 누락, 시퀀스 NEXTVAL 미사용 같은 다양한 패턴에서 나타난다.
본 글은 ORA-01400의 정확한 의미와 자주 발생하는 5가지 케이스, 해결 방법(명시 값·DEFAULT·DEFAULT ON NULL·BEFORE INSERT 트리거·IDENTITY 컬럼·NULL 허용으로 완화), DEFAULT vs DEFAULT ON NULL 차이까지 정리한 트러블슈팅 자료다.

이 글의 구성
01 에러 메시지와 카테고리
| 항목 | 내용 |
|---|---|
| 에러 코드 | ORA-01400 |
| 영문 메시지 | cannot insert NULL into ("스키마"."테이블"."컬럼") |
| Cause (공식) | An attempt was made to insert NULL into a column that has been defined as NOT NULL. |
| Action (공식) | INSERT 문에 해당 컬럼 값을 명시하거나 ALTER TABLE로 NOT NULL 제약을 완화 |
| 발생 영역 | INSERT·UPDATE·MERGE |
핵심 관찰 — 직접 NULL이 아니어도 발생
ORA-01400은 단순히 VALUES (NULL)처럼 명시적 NULL을 입력할 때만 발생하지 않는다. INSERT 컬럼 목록에서 NOT NULL 컬럼을 누락해 암시적 NULL이 되거나, 시퀀스 NEXTVAL을 빠뜨리는 등 간접적 패턴이 더 흔하다.
02 발생 원인 5가지
원인 1 — 명시적 NULL INSERT
INSERT INTO T VALUES (1, NULL)처럼 NOT NULL 컬럼에 직접 NULL을 넣는 가장 단순한 케이스다.
원인 2 — INSERT 컬럼 목록 누락 (암시적 NULL)
INSERT 컬럼 목록에 NOT NULL 컬럼을 포함하지 않으면 그 컬럼은 자동으로 NULL이 되어 에러가 발생한다. 신규 컬럼 추가 후 기존 코드에서 자주 발생한다.
원인 3 — UPDATE로 NOT NULL 컬럼을 NULL로 변경
UPDATE T SET col = NULL 같은 명령으로 NOT NULL 컬럼을 NULL로 만들 수 없다.
원인 4 — MERGE INSERT 절 NULL 매핑
MERGE 문의 WHEN NOT MATCHED THEN INSERT 부분에서 매핑되는 소스 데이터에 NULL이 포함되면 NOT NULL 컬럼에서 거부된다.
원인 5 — PK에 시퀀스 NEXTVAL 미사용
PK가 NOT NULL인데 INSERT 시 시퀀스 NEXTVAL을 호출하지 않거나 ID 값을 명시하지 않으면 NULL이 되어 에러가 발생한다.
03 재현 시나리오와 코드 예제
원인 1·2 — 명시적·암시적 NULL
CREATE TABLE emp (
id NUMBER NOT NULL,
name VARCHAR2(50) NOT NULL,
dept VARCHAR2(30)
);
-- ✗ 명시적 NULL
INSERT INTO emp VALUES (1, NULL, 'IT');
-- ORA-01400: cannot insert NULL into ("...EMP"."NAME")
-- ✗ NAME 컬럼 누락 → 암시적 NULL
INSERT INTO emp (id, dept) VALUES (2, 'HR');
-- ORA-01400
-- ✓ 모든 NOT NULL 컬럼에 값 제공
INSERT INTO emp (id, name, dept) VALUES (3, 'Alice', 'IT');
원인 5 — PK 시퀀스 미사용
-- emp 테이블의 id가 PK + NOT NULL
CREATE SEQUENCE seq_emp START WITH 1 INCREMENT BY 1;
-- ✗ ID 미지정 → NULL
INSERT INTO emp (name) VALUES ('Alice');
-- ORA-01400
-- ✓ 시퀀스 NEXTVAL 사용
INSERT INTO emp (id, name) VALUES (seq_emp.NEXTVAL, 'Alice');
04 해결 패턴 6가지
패턴 1 — 명시적 값 제공
INSERT/UPDATE 문에 NOT NULL 컬럼 값을 항상 명시한다. 가장 단순하고 확실한 방법이다.
패턴 2 — DEFAULT 절 (컬럼 누락 시만)
CREATE TABLE emp (
id NUMBER NOT NULL,
name VARCHAR2(50) DEFAULT '(unknown)' NOT NULL
);
-- ✓ INSERT 절에 name 누락 → DEFAULT 적용
INSERT INTO emp (id) VALUES (1);
-- ✗ 명시적 NULL은 DEFAULT 적용 안 됨
INSERT INTO emp (id, name) VALUES (2, NULL);
-- ORA-01400
패턴 3 — DEFAULT ON NULL (12c 이상)
CREATE TABLE emp (
id NUMBER NOT NULL,
name VARCHAR2(50) DEFAULT ON NULL '(unknown)' NOT NULL
);
-- ✓ 컬럼 누락이든 명시적 NULL이든 DEFAULT 적용
INSERT INTO emp (id) VALUES (1); -- name = '(unknown)'
INSERT INTO emp (id, name) VALUES (2, NULL); -- name = '(unknown)'
패턴 4 — IDENTITY 컬럼 (12c 이상, PK 자동 채우기)
CREATE TABLE emp (
id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY,
name VARCHAR2(50) NOT NULL
);
-- ✓ ID 자동 채워짐 (시퀀스 직접 사용 불필요)
INSERT INTO emp (name) VALUES ('Alice');
패턴 5 — BEFORE INSERT 트리거
CREATE OR REPLACE TRIGGER trg_emp_bi
BEFORE INSERT ON emp
FOR EACH ROW
BEGIN
IF :NEW.id IS NULL THEN
:NEW.id := seq_emp.NEXTVAL;
END IF;
IF :NEW.reg_dt IS NULL THEN
:NEW.reg_dt := SYSDATE;
END IF;
END;
/
패턴 6 — NOT NULL 제약 완화 (비즈니스상 NULL 허용 시)
-- 신중히 검토 후 적용
ALTER TABLE emp MODIFY (name NULL);
05 DEFAULT vs DEFAULT ON NULL
이 두 키워드 차이가 ORA-01400 방어에서 핵심이다.
| 시나리오 | DEFAULT | DEFAULT ON NULL |
|---|---|---|
| 컬럼 누락 INSERT | 기본값 적용 | 기본값 적용 |
| 명시적 NULL INSERT | NULL 그대로 → ORA-01400 | 기본값 적용 |
| 도입 버전 | 모든 버전 | Oracle 12c 이상 |
NOT NULL 컬럼의 견고한 영구 방어를 원한다면 DEFAULT ON NULL을 사용한다. 12c 미만에서는 BEFORE INSERT 트리거로 동일 효과를 만들 수 있다.
06 자주 묻는 질문 5가지
Q1DEFAULT가 정의되어 있는데 NULL을 넣으면 왜 에러인가
기본 DEFAULT는 INSERT 절에서 컬럼이 누락되었을 때만 적용된다. VALUES (NULL)처럼 명시적으로 NULL을 넣으면 DEFAULT가 적용되지 않고 그대로 NULL이 들어가려 하므로 NOT NULL 위반이 발생한다. 12c 이상이면 DEFAULT ON NULL로 변경하면 명시적 NULL도 기본값으로 치환된다.
Q2NOT NULL 제약을 그냥 없애면 안 되나
가능하지만 신중히 결정한다. NOT NULL은 데이터 무결성의 핵심 보호장치다. 비즈니스적으로 정말 NULL이 허용되는 컬럼이라면 완화가 맞지만, 단순히 에러를 회피하기 위해 제약을 푸는 것은 데이터 품질 저하를 가져온다. 가능하면 DEFAULT·DEFAULT ON NULL·트리거로 자동 채우는 방식이 안전하다.
Q3IDENTITY와 BEFORE INSERT 트리거 중 무엇이 좋나
단순 PK 자동 증가에는 IDENTITY 컬럼(12c+)이 더 깔끔하다. 코드도 짧고 시퀀스를 별도 관리할 필요 없다. 다만 ID 외에 reg_dt·user_id 같은 메타 컬럼도 함께 자동 채워야 한다면 BEFORE INSERT 트리거가 유연하다. 두 방식을 함께 쓰는 것도 가능하다.
Q4운영 테이블에 신규 NOT NULL 컬럼을 추가하다가 ORA-01400이 발생한다
기존 행에 해당 컬럼 값이 없어서 발생한다. 컬럼 추가 시 DEFAULT 값을 함께 지정하면 기존 행에 자동 채워진다. 예: ALTER TABLE T ADD col VARCHAR2(50) DEFAULT '(default)' NOT NULL. 11g 이상에서는 메타데이터만 변경되어 빠르게 처리된다.
Q5애플리케이션 코드에서 NULL이 들어오는 경우 어떻게 처리하나
애플리케이션 단에서 NVL 또는 동등한 처리로 기본값을 보장하거나, DB 레벨에서 DEFAULT ON NULL·트리거로 안전망을 두는 두 가지 방어선을 함께 적용하는 것이 견고하다. 어느 한 곳만 처리하면 다른 경로(직접 SQL·이관·외부 도구)에서 NULL이 흘러들어 에러가 발생할 수 있다.
07 결론
ORA-01400은 NOT NULL 제약의 본래 목적인 데이터 무결성을 지키기 위해 발생하는 에러다. 단순 코드 수정으로 해결되는 경우가 많지만, 영구 방어책으로는 DEFAULT ON NULL·IDENTITY·BEFORE INSERT 트리거 같은 DB 레벨 안전망이 더 견고하다.
실무 원칙은 다음과 같다.
첫째, 필수 값은 애플리케이션 단에서 명시적으로 채우고, DB 레벨에서 DEFAULT ON NULL·트리거로 이중 방어한다.
둘째, PK는 IDENTITY 컬럼 또는 시퀀스를 활용한 트리거로 자동 채우기를 표준화한다.
셋째, NOT NULL 제약 완화는 데이터 품질 저하 위험이 있으므로 비즈니스적 정당성이 명확할 때만 적용한다.
ORA-01400은 NOT NULL이 데이터 품질을 지키기 위해 정상 작동하는 신호다. 회피보다 DEFAULT ON NULL·IDENTITY·트리거로 견고한 방어선을 만든다.
— 단순 NULL 입력 외에도 컬럼 누락·시퀀스 미사용 같은 간접 패턴 주의
트러블슈팅 체크리스트
본 글은 Oracle Database NOT NULL 제약 위반 에러 ORA-01400의 일반적 원인과 해결 방법을 정리한 자료다. 운영 환경 적용 전 테스트 환경에서 충분히 검증한다.
#ORA01400 #cannotinsertNULL #오라클에러 #NOTNULL제약 #DEFAULT #DEFAULTONNULL #IDENTITY #BEFOREINSERT #시퀀스 #PLSQL트리거 #MERGE #PK자동채우기 #데이터무결성 #DB트러블슈팅 #SQL제약
댓글