본문 바로가기
IT

ORA-00904 invalid identifier — 부적합한 식별자·컬럼명 오타 에러 원인·해결·예방 완전 정리

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

ORA-00904 invalid identifier — 부적합한 식별자·컬럼명 오타 에러 원인·해결·예방 완전 정리

Oracle Database 개발자라면 누구나 한 번은 만나는 가장 흔한 에러 중 하나가 ORA-00904: "string": invalid identifier다. 컬럼명 한 글자 오타에서 시작해 큰따옴표·대소문자·예약어·alias 참조 문제까지 원인이 매우 다양하다. SQL을 처음 배우는 개발자뿐 아니라 시니어도 다른 스키마 객체를 다룰 때 자주 마주친다.

 

본 글은 ORA-00904의 정확한 의미와 6가지 발생 원인, 재현 시나리오 SQL, 단계별 해결 방법, 인접 에러(ORA-00942·00936·00911·00917)와의 차이까지 정리한 트러블슈팅 자료다.

ORA-00904

이 글의 구성

 

01에러 메시지와 의미
02발생 원인 6가지
03재현 시나리오 5가지
04해결 방법과 디버깅 순서
05인접 에러와의 차이
Q&A자주 묻는 질문 5가지

01 에러 메시지와 의미

항목 내용
에러 코드 ORA-00904
영문 메시지 "string": invalid identifier
한국어 메시지 "문자열": 부적합한 식별자
Cause (공식) The column name entered is either missing or invalid.
Action (공식) 컬럼명을 확인하고 오라클 명명 규칙을 따른다
발생 영역 SELECT·INSERT·UPDATE·DELETE의 컬럼명 참조 시점

Oracle 식별자(Identifier) 명명 규칙

  • 문자로 시작 (영문자·한글)
  • 30자 이내 (12c 이전), 128자 이내 (12.2 이상)
  • 영문자·숫자·_·$·# 허용
  • 예약어 사용 불가 (또는 큰따옴표로 escape)
  • 큰따옴표로 감싸면 대소문자·특수문자 허용 (case-sensitive)

💡 핵심 관찰 — 식별자 vs 리터럴

SQL에서 큰따옴표(")는 식별자(컬럼·테이블명) 감싸기, 작은따옴표(')는 문자 리터럴 감싸기다. 둘을 섞으면 100% ORA-00904가 발생한다. WHERE name = "홍길동" 같은 문장은 "홍길동"이라는 이름의 컬럼을 찾으려고 시도하다 실패한다.


02 발생 원인 6가지

원인 1 — 컬럼명 오타

가장 흔한 원인. EMP_NAEM 같은 철자 실수, NAME 대신 NMAE처럼 키보드 자판 실수가 빈번하다. 메시지에 따옴표로 표시된 문자열이 곧 잘못 입력된 식별자다.

원인 2 — 따옴표 처리 잘못

큰따옴표(식별자)와 작은따옴표(리터럴)를 혼동한 경우. WHERE name = "SCOTT"은 "SCOTT"이라는 컬럼을 찾으려 시도해 실패한다. 'SCOTT'로 써야 문자 리터럴이 된다.

원인 3 — 대소문자 차이

Oracle 기본 동작은 따옴표 없는 식별자를 모두 대문자로 저장한다. 하지만 큰따옴표로 감싸 생성한 컬럼은 입력한 그대로(case-sensitive) 저장돼 매번 같은 케이스로 조회해야 한다. CREATE TABLE t("FirstName" ...)SELECT firstname FROM t는 실패한다.

원인 4 — 예약어를 컬럼명으로 사용

USER, DATE, LEVEL, COMMENT, SIZE, NUMBER 같은 예약어를 컬럼명으로 사용하면 발생한다. DDL 자체가 막히기도 하고, 큰따옴표로 강제 생성한 경우엔 조회 시점에 ORA-00904가 발생한다.

원인 5 — alias 잘못 참조

SELECT 절에서 만든 alias는 같은 쿼리의 WHERE·GROUP BY·HAVING에서 참조할 수 없다. SQL 파싱 순서상 SELECT보다 이들이 먼저 실행되기 때문이다. ORDER BY에서만 alias 사용이 가능하다.

원인 6 — 테이블은 있지만 컬럼이 없음

DDL 변경 후 컬럼이 삭제·이름변경된 경우. 또는 동의어(synonym) 누락으로 잘못된 객체를 참조하는 경우. 다른 스키마의 테이블을 별칭 없이 참조했을 때도 자주 발생한다.


03 재현 시나리오 5가지

시나리오 1 — 단순 오타

-- ✗ 컬럼명 오타 (NAEM → NAME)
SELECT emp_naem FROM employees;
-- ORA-00904: "EMP_NAEM": invalid identifier

-- ✓ 정정
SELECT emp_name FROM employees;

시나리오 2 — 따옴표 혼동

-- ✗ 큰따옴표로 리터럴 시도
SELECT * FROM employees WHERE first_name = "SCOTT";
-- ORA-00904: "SCOTT": invalid identifier

-- ✓ 작은따옴표 사용
SELECT * FROM employees WHERE first_name = 'SCOTT';

시나리오 3 — 대소문자 (큰따옴표 생성 컬럼)

-- 큰따옴표로 case-sensitive 생성
CREATE TABLE t1 ("FirstName" VARCHAR2(50));

-- ✗ 무따옴표 또는 케이스 다르게 조회
SELECT firstname FROM t1;
SELECT FIRSTNAME FROM t1;
-- 둘 다 ORA-00904

-- ✓ 같은 따옴표·케이스로 조회
SELECT "FirstName" FROM t1;

시나리오 4 — 예약어 컬럼명

-- ✗ 예약어 COMMENT를 컬럼명으로
CREATE TABLE t2 (id NUMBER, comment VARCHAR2(100));
-- ORA-00904: "COMMENT": invalid identifier

-- ✓ 일반 식별자로 변경 (권장)
CREATE TABLE t2 (id NUMBER, comment_text VARCHAR2(100));

시나리오 5 — WHERE에서 alias 참조

-- ✗ SELECT에서 만든 alias를 WHERE에서 참조
SELECT (price * qty) AS total
FROM   orders
WHERE  total > 1000;
-- ORA-00904: "TOTAL": invalid identifier

-- ✓ 표현식 반복 또는 서브쿼리·WITH 절 사용
SELECT (price * qty) AS total
FROM   orders
WHERE  (price * qty) > 1000;

-- 또는 WITH 절
WITH calc AS (
  SELECT (price * qty) AS total FROM orders
)
SELECT * FROM calc WHERE total > 1000;

04 해결 방법과 디버깅 순서

해결 방법 5가지

방법 설명
컬럼명 확인 USER_TAB_COLUMNS 또는 DESC 테이블명으로 실제 저장된 컬럼명 확인
따옴표 통일 식별자는 큰따옴표 또는 무따옴표, 리터럴은 작은따옴표로 분리
대소문자 일치 큰따옴표로 생성한 컬럼은 생성 시 대소문자 그대로 조회
예약어 회피 comment → comment_text, date → created_date 식으로 변경
alias 위치 정정 WHERE·GROUP BY·HAVING은 표현식 반복 또는 WITH 절·서브쿼리

디버깅 명령

-- 실제 컬럼명 확인
SELECT column_name
FROM   user_tab_columns
WHERE  table_name = 'EMPLOYEES';

-- SQL*Plus / SQL Developer
DESC employees;

-- 다른 스키마 객체 확인 (권한 필요)
SELECT owner, column_name
FROM   all_tab_columns
WHERE  table_name = 'EMPLOYEES';

-- 동의어(synonym) 확인
SELECT synonym_name, table_owner, table_name
FROM   user_synonyms
WHERE  synonym_name = 'EMPLOYEES';

단계별 진단 절차

디버깅 흐름

 

01에러 메시지의 따옴표 안 문자열을 확인 — 곧 문제의 식별자다.
02DESC 또는 USER_TAB_COLUMNS로 실제 컬럼명·대소문자 확인.
03큰따옴표·작은따옴표 위치를 점검 (식별자 vs 리터럴).
04에러 위치가 WHERE/GROUP BY/HAVING 절이면 alias 참조 여부 확인.
05다른 스키마 객체면 ALL_TAB_COLUMNS·동의어·권한 점검.

ORA-00904는 단순 오타 외에 따옴표·대소문자·예약어·alias·동의어까지 6가지 원인이 섞여 있다. 메시지의 따옴표 안 문자열부터 확인하는 것이 가장 빠른 진단이다.

 

━ 식별자는 큰따옴표, 리터럴은 작은따옴표


05 인접 에러와의 차이

에러 코드 검사 대상 전형적 시나리오
ORA-00904 컬럼·식별자 자체 없음 컬럼명 오타·따옴표·대소문자·예약어·alias
ORA-00942 테이블·뷰 객체 없음 테이블명 오타·권한 없음·동의어 누락
ORA-00936 표현식 누락 SELECT 뒤 컬럼 누락, FROM 누락
ORA-00911 잘못된 문자 @·!·$ 등 허용 안 된 특수문자
ORA-00917 콤마 누락 INSERT 컬럼 목록·VALUES 콤마 누락

ORA-00904와 ORA-00942의 결정적 차이는 객체 단위다. ORA-00904는 컬럼 단위(테이블은 있지만 컬럼이 없음), ORA-00942는 테이블·뷰 단위(객체 자체가 없거나 권한 없음)다. 메시지에서 어떤 식별자가 따옴표로 표시되는지 보면 즉시 구분된다.


06 자주 묻는 질문 5가지

Q1컬럼이 분명히 있는데 왜 invalid identifier가 나오나

세 가지를 의심한다. 첫째, 다른 스키마의 테이블이라 권한 부족 또는 동의어 누락. ALL_TAB_COLUMNS와 USER_SYNONYMS를 함께 확인한다. 둘째, 큰따옴표로 생성한 case-sensitive 컬럼인데 케이스가 어긋남. 셋째, DDL 변경으로 컬럼이 삭제·이름변경됐는데 본인이 모름. DESC로 실제 상태를 확인한다.

Q2큰따옴표와 작은따옴표 차이를 다시 정리해 달라

큰따옴표 "는 식별자(컬럼·테이블·alias·스키마명)를 감싼다. 작은따옴표 '는 문자 리터럴을 감싼다. 숫자는 따옴표 없이 그대로 쓴다. 한 가지 규칙으로 외우면 "이름은 큰따옴표, 값은 작은따옴표".

Q3SELECT의 alias를 같은 쿼리 WHERE에서 정말 못 쓰나

못 쓴다. SQL 파싱 순서가 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY이므로 SELECT에서 만든 alias는 WHERE 시점에 아직 존재하지 않는다. ORDER BY에서만 alias 사용이 가능하다. 회피 방법은 표현식 반복, 서브쿼리, WITH 절(CTE) 중 하나다. WITH 절이 가독성이 가장 좋다.

Q4예약어 컬럼명을 피하는 방법은

가장 안전한 방법은 컬럼명 자체를 변경하는 것이다. date → created_date, comment → comment_text, user → user_id, level → user_level, size → file_size 같이 의미를 보강한 이름으로 바꾸면 가독성도 좋아진다. 큰따옴표로 강제 생성하는 방법도 있지만 매번 큰따옴표로 조회해야 해서 권장하지 않는다.

Q5Oracle은 왜 기본적으로 식별자를 대문자로 저장하나

SQL 표준(ANSI/ISO SQL)이 무따옴표 식별자를 대소문자 무시(case-insensitive)로 정의했고, Oracle은 이를 내부적으로 대문자 저장으로 구현했다. 따라서 무따옴표로 만든 emp_name·EMP_NAME·Emp_Name은 모두 같은 EMP_NAME으로 저장된다. 큰따옴표를 쓰는 순간 표준 규칙이 깨져 case-sensitive로 동작한다.


07 결론

ORA-00904는 단순 오타로 보이지만 실제로는 따옴표·대소문자·예약어·alias·동의어까지 여섯 가지 원인이 섞여 있는 에러다. 메시지 안 따옴표 문자열을 먼저 확인하고, USER_TAB_COLUMNS·DESC로 실제 객체 상태를 점검하는 흐름이 가장 빠른 진단이다.

 

실무 원칙은 다음과 같다.

 

첫째, 식별자는 큰따옴표 또는 무따옴표로, 문자 리터럴은 작은따옴표로 명확히 분리한다.

둘째, 큰따옴표로 case-sensitive 컬럼을 만들지 않는다. 부득이하게 만들면 모든 쿼리에서 같은 따옴표·케이스로 일관되게 참조한다.

셋째, 예약어를 컬럼명으로 사용하지 않는다. 호환성·가독성을 위해 컬럼명 자체를 변경한다.

넷째, alias는 SELECT에서 정의해 ORDER BY에서만 사용하고, WHERE·GROUP BY·HAVING이 필요하면 표현식 반복 또는 WITH 절을 사용한다.

다섯째, 다른 스키마 객체 접근 시 동의어·권한을 사전에 확인한다.

✅ ORA-00904 트러블슈팅 체크리스트

01메시지 따옴표 안 문자열 확인 — 곧 문제의 식별자
02DESC 테이블명 또는 USER_TAB_COLUMNS로 실제 컬럼 점검
03큰따옴표(식별자) vs 작은따옴표(리터럴) 위치 점검
04큰따옴표 생성 컬럼은 case-sensitive — 케이스 일치 확인
05예약어 컬럼명은 회피 — comment_text·created_date 식 변경
06alias 사용 위치 — ORDER BY 가능, WHERE/GROUP BY/HAVING 불가
07다른 스키마 객체는 ALL_TAB_COLUMNS·USER_SYNONYMS·권한 확인

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

 

#ORA00904 #invalidIdentifier #오라클에러 #컬럼명오타 #식별자 #큰따옴표 #작은따옴표 #예약어 #SQL_alias #USER_TAB_COLUMNS #WITH절 #서브쿼리 #ORA00942 #ORA00936 #SQL디버깅

반응형

댓글