ORA-00984 column not allowed here — 컬럼 위치 오류 에러 원인·해결·예방 완전 정리
ORA-00984: column not allowed here는 Oracle Database에서 SQL을 작성할 때 자주 마주치는 에러 중 하나다. 가장 흔한 원인은 INSERT VALUES 절에서 문자열 리터럴을 작은따옴표로 감싸지 않아 Oracle이 그 문자열을 컬럼명(식별자)으로 해석한 경우다. 그 외에도 DEFAULT 절에 컬럼 참조, 트리거에서 :NEW/:OLD prefix 누락, INSERT VALUES에 다른 테이블 컬럼 직접 참조 등 "컬럼 사용 불가 위치에 컬럼명을 사용한 경우" 모두 이 에러로 묶인다.
본 글은 ORA-00984의 정확한 의미와 5가지 발생 원인, 재현 SQL, 따옴표·INSERT SELECT·:NEW/:OLD를 활용한 해결 방법, 인접 에러(ORA-00904·00911·00936)와의 차이까지 정리한 트러블슈팅 자료다.

이 글의 구성
01 에러 메시지와 의미
| 항목 | 내용 |
|---|---|
| 에러 코드 | ORA-00984 |
| 영문 | column not allowed here |
| 한국어 | 열을 사용할 수 없습니다 |
| Cause | 컬럼 식별자를 사용할 수 없는 위치에 컬럼 참조가 들어감 |
| 대표 시나리오 | INSERT VALUES 작은따옴표 누락 → 문자열이 컬럼명으로 해석 |
💡 핵심 관찰 — 따옴표 종류가 결과를 가른다
SQL에서 작은따옴표(')는 문자 리터럴, 큰따옴표(")는 식별자(컬럼·테이블)를 감싼다. INSERT INTO emp VALUES (1, kim)처럼 따옴표 없이 쓰면 Oracle은 kim을 컬럼명으로 해석하고, INSERT VALUES 자리는 컬럼명을 받을 수 없으므로 ORA-00984를 던진다.
02 발생 원인 5가지
원인 1 — INSERT VALUES 작은따옴표 누락
가장 흔한 원인. 문자열·날짜 리터럴을 작은따옴표 없이 작성하면 Oracle이 컬럼명으로 해석한다. INSERT INTO emp VALUES (1, kim) → kim을 식별자로 처리하다 ORA-00984.
원인 2 — 큰따옴표로 문자열 감싸기
다른 DB(MySQL·MSSQL 일부 모드)에서는 큰따옴표도 문자열로 동작하지만 Oracle은 큰따옴표를 식별자 전용으로 본다. INSERT INTO emp VALUES (1, "kim")은 "kim"이라는 컬럼명을 INSERT VALUES에 쓰려고 시도하다 실패.
원인 3 — INSERT VALUES에 다른 테이블 컬럼 참조
INSERT INTO emp VALUES (1, dept.dname)처럼 VALUES 절에 다른 테이블의 컬럼을 직접 참조하면 발생한다. VALUES 절은 상수·리터럴·시퀀스·함수 호출만 허용한다. 다른 테이블 값을 넣으려면 INSERT ... SELECT 형식을 써야 한다.
원인 4 — DEFAULT 절에 컬럼·의사컬럼 참조
DEFAULT 값으로 사용할 수 있는 것은 상수, SYSDATE, USER, SYS_GUID 같은 결정적 함수다. 다른 컬럼명, LEVEL, ROWNUM, CURRVAL 같은 의사컬럼은 DEFAULT에 사용할 수 없어 ORA-00984가 발생한다. (12c부터는 시퀀스 NEXTVAL이 예외적으로 허용된다.)
원인 5 — 트리거에서 :NEW/:OLD 누락
트리거 본문에서 새로 입력되는 값·이전 값을 참조할 때는 :NEW.컬럼명·:OLD.컬럼명 prefix가 필수다. prefix 없이 그냥 컬럼명만 쓰면 INSERT/UPDATE의 VALUES 자리에 컬럼명이 들어간 것처럼 처리되어 ORA-00984가 발생한다.
03 재현 시나리오와 해결 코드
시나리오 1 — 작은따옴표 누락
-- ✗ 작은따옴표 없이 문자열
INSERT INTO emp (id, ename) VALUES (1, kim);
-- ORA-00984: column not allowed here
-- ✓ 작은따옴표 추가
INSERT INTO emp (id, ename) VALUES (1, 'kim');
시나리오 2 — 큰따옴표 사용
-- ✗ 큰따옴표는 식별자용
INSERT INTO emp (id, ename) VALUES (1, "kim");
-- ORA-00984
-- ✓ 작은따옴표로 변경
INSERT INTO emp (id, ename) VALUES (1, 'kim');
시나리오 3 — INSERT VALUES에 다른 테이블 컬럼
-- ✗ VALUES에 다른 테이블 컬럼
INSERT INTO emp_history (emp_id, dept_name)
VALUES (100, dept.dname);
-- ORA-00984
-- ✓ INSERT ... SELECT 패턴
INSERT INTO emp_history (emp_id, dept_name)
SELECT 100, d.dname
FROM dept d
WHERE d.dept_id = 10;
시나리오 4 — DEFAULT에 컬럼 참조 (11g 이하)
-- ✗ DEFAULT에 시퀀스 NEXTVAL (11g 이하)
CREATE TABLE t (id NUMBER DEFAULT seq_t.NEXTVAL);
-- 11g 이하: ORA-00984
-- 12c 이상: 정상 (Identity 컬럼·시퀀스 DEFAULT 허용)
-- ✓ 11g 이하 — 트리거로 우회
CREATE OR REPLACE TRIGGER trg_t_id
BEFORE INSERT ON t
FOR EACH ROW
BEGIN
IF :NEW.id IS NULL THEN
:NEW.id := seq_t.NEXTVAL;
END IF;
END;
/
-- ✓ 12c 이상 — Identity 컬럼
CREATE TABLE t (
id NUMBER GENERATED ALWAYS AS IDENTITY
);
시나리오 5 — 트리거에서 :NEW 누락
-- ✗ :NEW prefix 누락
CREATE OR REPLACE TRIGGER trg_emp_log
AFTER INSERT ON emp
FOR EACH ROW
BEGIN
INSERT INTO emp_log(emp_id, action)
VALUES (emp_id, 'INS'); -- ✗ emp_id가 어디 컬럼?
END;
/
-- ✓ :NEW.컬럼명 prefix 명시
CREATE OR REPLACE TRIGGER trg_emp_log
AFTER INSERT ON emp
FOR EACH ROW
BEGIN
INSERT INTO emp_log(emp_id, action)
VALUES (:NEW.emp_id, 'INS');
END;
/
04 DEFAULT 값과 12c+ NEXTVAL 변경
DEFAULT 절은 Oracle 버전별로 허용 범위가 다르다.
| DEFAULT 가능 여부 | 11g 이하 | 12c 이상 |
|---|---|---|
| 상수 (리터럴) | 가능 | 가능 |
| SYSDATE·USER·SYS_GUID | 가능 | 가능 |
| 시퀀스 NEXTVAL/CURRVAL | 불가 (ORA-00984) → 트리거 우회 | 가능 (12.1+ NEXTVAL, 12.2+ CURRVAL) |
| Identity 컬럼 | 없음 | 가능 (12c+) |
| 다른 컬럼 참조 | 불가 | 불가 (가상 컬럼 사용) |
| LEVEL·ROWNUM 의사컬럼 | 불가 | 불가 |
12c 이상에서는 시퀀스를 DEFAULT에 직접 사용할 수 있다(DEFAULT seq.NEXTVAL). 또 Identity 컬럼이 추가되어 자동 증가 기본키 구현이 더 간단해졌다. 11g 이하에서는 BEFORE INSERT 트리거로 우회하는 게 일반적이다.
ORA-00984의 본질은 "이 위치는 값이 와야 하는데 식별자가 왔다"는 신호다. 작은따옴표 하나, :NEW prefix 하나, INSERT SELECT 변경 하나로 대부분 해결된다.
━ 따옴표는 작은따옴표, 컬럼 참조는 SELECT로
05 인접 에러와의 차이
| 에러 코드 | 검사 대상 | 전형적 시나리오 |
|---|---|---|
| ORA-00984 | 컬럼 사용 불가 위치 | INSERT VALUES 따옴표 누락·DEFAULT 컬럼 참조 |
| ORA-00904 | 존재하지 않는 식별자 | 컬럼명 오타·예약어·대소문자 |
| ORA-00911 | 잘못된 문자 | @·!·; 같은 허용 안 된 특수문자 |
| ORA-00936 | 표현식 누락 | SELECT 뒤 컬럼 누락·FROM 누락 |
| ORA-01756 | 문자열 미종료 | 작은따옴표 한쪽만 입력 |
ORA-00984와 ORA-00904는 비슷해 보이지만 검사 단계가 다르다. ORA-00904는 "그 컬럼명이 존재하는가"를 검사하다 실패, ORA-00984는 "이 위치에 컬럼이 올 수 있는가"를 검사하다 실패다. INSERT VALUES에 따옴표 없는 문자열은 두 에러 모두 가능성이 있지만, 그 문자열이 실제 컬럼명과 일치하면 ORA-00984, 그렇지 않으면 ORA-00904가 나오는 경향이 있다.
06 자주 묻는 질문 5가지
Q1큰따옴표와 작은따옴표 차이를 다시 정리해 달라
Oracle에서 큰따옴표(")는 식별자(컬럼·테이블·alias)를 감싸는 용도이고, 작은따옴표(')는 문자 리터럴을 감싸는 용도다. MySQL이나 PostgreSQL의 일부 모드에서는 큰따옴표가 문자열로도 동작할 수 있지만 Oracle은 SQL 표준을 따라 엄격히 구분한다. 외워두면 좋은 한 줄 — "이름은 큰따옴표, 값은 작은따옴표".
Q2INSERT VALUES에서 다른 테이블 컬럼을 참조하려면
VALUES 절에는 상수·리터럴·시퀀스·함수만 들어갈 수 있다. 다른 테이블의 값을 넣으려면 INSERT INTO ... SELECT ... 형식으로 바꿔야 한다. WHERE 절·JOIN을 활용해 원하는 값을 선택해 그대로 INSERT할 수 있다.
Q3DEFAULT 값에 다른 컬럼을 참조할 방법이 있나
불가능하다. DEFAULT는 행 단위 연산이 아니라 컬럼 정의 시점의 정적 값으로, 같은 행의 다른 컬럼을 참조할 수 없다. 가상 컬럼(Virtual Column)을 사용하거나 BEFORE INSERT 트리거에서 :NEW.컬럼 = ... 식으로 우회한다. 가상 컬럼은 CREATE TABLE t (price NUMBER, tax NUMBER GENERATED ALWAYS AS (price * 0.1)) 형식으로 만든다.
Q4트리거에서 :NEW와 :OLD는 정확히 어떻게 다른가
:NEW는 INSERT·UPDATE 직후의 새 값이고, :OLD는 UPDATE·DELETE 직전의 이전 값이다. INSERT 트리거는 :OLD가 모두 NULL, DELETE 트리거는 :NEW가 모두 NULL이다. UPDATE 트리거는 두 가지 모두 의미가 있다. 두 prefix 모두 콜론 포함 정확한 표기가 필수이며, 빠뜨리면 ORA-00984가 발생한다.
Q5같은 코드가 12c에서는 되고 11g에서는 안 되는 경우는
시퀀스 DEFAULT가 대표 사례다. 12c 이상에서는 id NUMBER DEFAULT seq.NEXTVAL이 정상 동작하지만 11g 이하에서는 ORA-00984가 발생한다. 11g 이하 호환성이 필요하면 Identity 컬럼·시퀀스 DEFAULT 대신 BEFORE INSERT 트리거로 우회한다. Oracle 버전을 명시해 코드 작성 환경을 통일하는 것이 운영 안정성에 도움이 된다.
07 결론
ORA-00984는 "이 위치에 값이 와야 하는데 식별자가 왔다"는 단순한 신호다. INSERT VALUES 작은따옴표 누락이 가장 흔한 원인이며, 그 외에도 DEFAULT 절 컬럼 참조, 트리거 :NEW/:OLD 누락, INSERT VALUES에 다른 테이블 컬럼 직접 참조 같은 패턴이 같은 에러로 묶인다.
실무 원칙은 다음과 같다.
첫째, 문자열·날짜 리터럴은 반드시 작은따옴표로 감싼다. 큰따옴표는 식별자 전용이라는 점을 기억한다.
둘째, INSERT VALUES에는 상수·리터럴·시퀀스·함수만 들어간다. 다른 테이블 값이 필요하면 INSERT ... SELECT 형식으로 변경한다.
셋째, DEFAULT 값은 상수·SYSDATE·USER·SYS_GUID 같은 결정적 표현만 가능하다. 다른 컬럼 참조는 가상 컬럼이나 트리거로 우회한다.
넷째, 트리거 본문에서 새/이전 값은 :NEW·:OLD prefix를 반드시 명시한다. 콜론 포함 정확한 표기가 필수다.
다섯째, 12c 이상에서는 시퀀스 DEFAULT와 Identity 컬럼이 추가됐다. 운영 환경의 Oracle 버전을 명시해 코드 작성 환경을 통일한다.
✅ ORA-00984 트러블슈팅 체크리스트
본 글은 Oracle Database 에러 ORA-00984의 일반적 원인과 해결 방법을 정리한 자료다. 운영 환경 적용 전 테스트 환경에서 충분히 검증한다.
#ORA00984 #columnNotAllowedHere #오라클에러 #INSERT_VALUES #작은따옴표 #큰따옴표 #DEFAULT절 #시퀀스NEXTVAL #Identity컬럼 #트리거_NEW #트리거_OLD #INSERT_SELECT #ORA00904 #ORA00911 #SQL디버깅
댓글