본문 바로가기
IT

ORA-00984 column not allowed here — 컬럼 위치 오류 에러 원인·해결·예방 완전 정리

by 샤나엘 2026. 5. 20.
반응형

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)와의 차이까지 정리한 트러블슈팅 자료다.

ORA-00984

 

이 글의 구성

 

01에러 메시지와 의미
02발생 원인 5가지
03재현 시나리오와 해결 코드
04DEFAULT 값과 12c+ NEXTVAL 변경
05인접 에러와의 차이
Q&A자주 묻는 질문 5가지

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 트러블슈팅 체크리스트

 

01INSERT VALUES에 작은따옴표 누락된 문자열 확인
02큰따옴표로 문자열 감싼 곳 → 작은따옴표로 변경
03다른 테이블 컬럼 참조 → INSERT ... SELECT 패턴으로 전환
04DEFAULT 절은 상수·SYSDATE·USER만 — 컬럼·LEVEL·ROWNUM 금지
05트리거에서 :NEW.col·:OLD.col prefix 필수 (콜론 포함)
0611g 이하는 시퀀스 DEFAULT 불가 — 트리거 우회 또는 12c 업그레이드
0712c 이상은 Identity 컬럼·NEXTVAL DEFAULT로 자동 증가 키 단순화

본 글은 Oracle Database 에러 ORA-00984의 일반적 원인과 해결 방법을 정리한 자료다. 운영 환경 적용 전 테스트 환경에서 충분히 검증한다.

 

#ORA00984 #columnNotAllowedHere #오라클에러 #INSERT_VALUES #작은따옴표 #큰따옴표 #DEFAULT절 #시퀀스NEXTVAL #Identity컬럼 #트리거_NEW #트리거_OLD #INSERT_SELECT #ORA00904 #ORA00911 #SQL디버깅

반응형

댓글