본문 바로가기
IT

ORA-00918 column ambiguously defined — 조인 컬럼 모호 에러 원인·해결·예방 완전 정리

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

ORA-00918 column ambiguously defined — 조인 컬럼 모호 에러 원인·해결·예방 완전 정리

Oracle Database에서 두 개 이상의 테이블을 조인할 때 가장 자주 만나는 에러 중 하나가 ORA-00918: column ambiguously defined다. 양 테이블에 같은 이름의 컬럼이 존재할 때 SELECT·WHERE·ORDER BY에서 그 컬럼을 prefix 없이 참조하면 즉시 발생한다. 특히 PK·FK가 동일한 이름인 설계(emp.dept_id ↔ dept.dept_id)에서는 거의 100% 마주치는 에러다.

 

본 글은 ORA-00918의 정확한 의미, 5가지 발생 원인, 재현 SQL, alias prefix·USING·ON 절을 활용한 해결 방법, NATURAL JOIN의 위험성, 인접 에러(ORA-25154·25155·00957)와의 차이까지 정리한 트러블슈팅 자료다.

ORA-00918

이 글의 구성

 

01에러 메시지와 의미
02발생 원인 5가지
03재현 시나리오와 해결 코드
04NATURAL JOIN vs USING vs ON
05인접 에러와의 차이
Q&A자주 묻는 질문 5가지

01 에러 메시지와 의미

항목 내용
에러 코드 ORA-00918
영문 column ambiguously defined
한국어 열의 정의가 애매합니다
Cause 조인 시 양 테이블에 같은 이름의 컬럼이 존재하는데 prefix 없이 참조
발생 시점 SELECT·WHERE·ORDER BY·HAVING 절의 컬럼 참조

💡 핵심 관찰 — "어느 테이블의 컬럼이냐"의 모호함

Oracle 옵티마이저는 SQL 파싱 단계에서 모든 컬럼 참조를 특정 테이블에 매핑해야 한다. JOIN한 두 테이블에 같은 이름이 있고 prefix가 없으면 "어느 쪽?"이 결정되지 않아 즉시 ORA-00918을 던진다. 해결의 핵심은 "모든 컬럼 참조에 prefix를 붙이거나 USING으로 명시"다.


02 발생 원인 5가지

원인 1 — PK·FK 동명 컬럼

emp.dept_id ↔ dept.dept_id처럼 PK·FK 컬럼이 같은 이름인 일반적 설계에서 가장 흔히 발생한다. 두 컬럼이 모두 결과셋에 노출될 가능성이 있으므로 prefix 없이는 옵티마이저가 결정 불가.

원인 2 — SELECT·WHERE·ORDER BY prefix 누락

JOIN에서 alias prefix(e.·d.)를 빠뜨린 채 SELECT·WHERE·ORDER BY에서 동명 컬럼을 그대로 참조하는 경우. ON 절은 옳지만 다른 절에서 잘못 쓴 케이스가 많다.

원인 3 — USING 절 컬럼에 prefix 부착 (ORA-25154 사례)

USING으로 조인한 컬럼은 두 테이블의 컬럼이 하나로 병합돼 "소속 테이블"이 사라진다. 그 컬럼에 prefix를 붙이면 ORA-25154가 발생한다. ORA-00918과 같은 모호 컬럼 그룹의 사촌 격 에러다.

원인 4 — NATURAL JOIN 자동 조인 컬럼에 prefix (ORA-25155)

NATURAL JOIN은 양 테이블의 동명 컬럼을 자동으로 조인 조건으로 사용한다. 결과셋에서 그 컬럼이 단일화되므로 prefix를 붙이면 ORA-25155가 발생한다. NATURAL JOIN 자체가 스키마 변경에 취약해 운영 환경에서는 피하는 게 권장된다.

원인 5 — 인라인뷰·서브쿼리 결과 컬럼명 충돌

인라인뷰 안에서 SELECT *로 두 테이블 컬럼을 모두 노출하면 결과셋에 동명 컬럼이 두 개 생긴다. 그 인라인뷰를 외부에서 다시 참조할 때 ORA-00918이 발생한다. SELECT *는 가급적 회피하고 필요한 컬럼만 alias로 명시하는 게 안전하다.


03 재현 시나리오와 해결 코드

시나리오 1 — SELECT 절 prefix 누락

-- ✗ SELECT에 prefix 없음
SELECT dept_id, ename, dname
FROM   emp e
JOIN   dept d ON e.dept_id = d.dept_id;
-- ORA-00918: column ambiguously defined

-- ✓ alias prefix 명시
SELECT e.dept_id, e.ename, d.dname
FROM   emp e
JOIN   dept d ON e.dept_id = d.dept_id;

시나리오 2 — WHERE 절 모호 참조

-- ✗ WHERE에 prefix 없음
SELECT e.ename
FROM   emp e JOIN dept d ON e.dept_id = d.dept_id
WHERE  dept_id = 10;

-- ✓ 어느 테이블의 컬럼인지 명시
SELECT e.ename
FROM   emp e JOIN dept d ON e.dept_id = d.dept_id
WHERE  d.dept_id = 10;

시나리오 3 — USING으로 단순화

-- ✓ USING — 조인 컬럼을 하나로 병합
SELECT dept_id, e.ename, d.dname
FROM   emp e JOIN dept d USING (dept_id);
-- dept_id는 prefix 없이 참조 가능 (USING으로 통합됨)

-- ✗ USING 컬럼에 prefix 붙이면 ORA-25154
SELECT e.dept_id FROM emp e JOIN dept d USING (dept_id);

시나리오 4 — ORDER BY 모호 참조

-- ✗ ORDER BY에 prefix 없음
SELECT e.*, d.*
FROM   emp e JOIN dept d ON e.dept_id = d.dept_id
ORDER BY dept_id;

-- ✓ prefix 또는 SELECT 위치 번호로 정렬
SELECT e.dept_id AS emp_dept_id, e.ename, d.dname
FROM   emp e JOIN dept d ON e.dept_id = d.dept_id
ORDER BY emp_dept_id;

시나리오 5 — 인라인뷰 SELECT * 회피

-- ✗ 인라인뷰 SELECT * → 외부에서 충돌
SELECT dept_id
FROM (
  SELECT * FROM emp e
  JOIN dept d ON e.dept_id = d.dept_id
);

-- ✓ 인라인뷰에서 필요한 컬럼만 alias 부여
SELECT emp_dept_id
FROM (
  SELECT e.dept_id AS emp_dept_id, e.ename, d.dname
  FROM   emp e JOIN dept d ON e.dept_id = d.dept_id
);

04 NATURAL JOIN vs USING vs ON

구분 NATURAL JOIN USING ON
조인 조건 동명 컬럼 자동 지정한 컬럼만 자유 표현식
조인 컬럼 prefix 금지 (ORA-25155) 금지 (ORA-25154) 필수
결과 컬럼 수 조인 컬럼 1개로 병합 조인 컬럼 1개로 병합 양쪽 모두 2개 유지
스키마 변경 영향 매우 큼 — 컬럼 추가만으로 조인 조건 변경 중간 — 컬럼 이름 동일 시 가능 최소 — 명시 조건만 적용
권장 운영 환경 회피 단순 조회 OK 실무 표준

세 가지 조인 방식의 결정적 차이는 "조인 컬럼의 소속 유지 여부"다. ON 절은 조인 후에도 양 테이블의 컬럼을 별도로 유지하므로 prefix가 필수다. USING과 NATURAL JOIN은 조인 컬럼이 하나로 통합돼 prefix가 금지된다.

 

실무에서는 ON 절이 표준이다. NATURAL JOIN은 스키마 변경(컬럼 추가)만으로 조인 조건이 의도와 다르게 바뀔 수 있어 운영 환경에서 권장되지 않는다. USING은 단순 조회에서 가독성이 좋지만, 복잡한 조인이나 ORM 매핑에서는 ON 절의 명시성이 더 안전하다.

ORA-00918을 막는 한 가지 습관 — 모든 컬럼 참조에 alias prefix를 붙인다. 한 줄짜리 SELECT라도 e.id·d.id로 쓰는 습관이 조인 확장 시 자유도를 만든다.

 

━ alias는 1~3자 소문자, ON 절이 실무 표준


05 인접 에러와의 차이

에러 코드 검사 대상 전형적 시나리오
ORA-00918 조인 컬럼 모호 JOIN 시 동명 컬럼에 prefix 누락
ORA-00904 식별자 자체 없음 컬럼명 오타·따옴표·예약어
ORA-00936 표현식 누락 SELECT 뒤 컬럼 누락·FROM 누락
ORA-00957 동명 컬럼 중복 지정 CREATE/INSERT 시 같은 컬럼명 두 번
ORA-25154 USING 컬럼 prefix USING 조인 컬럼에 alias 부착
ORA-25155 NATURAL JOIN 컬럼 prefix NATURAL 조인 자동 컬럼에 alias 부착

ORA-00918·25154·25155는 모두 "조인 컬럼 처리 실수"라는 같은 그룹의 에러다. 차이는 어떤 조인 방식을 사용했는지에 있다. ORA-00918은 ON 절 또는 일반 조인에서 prefix가 누락된 경우이고, ORA-25154/25155는 반대로 USING/NATURAL 조인 컬럼에 prefix를 잘못 붙인 경우다.


06 자주 묻는 질문 5가지

Q1USING 사용 시 왜 prefix 금지인가

USING은 양 테이블의 동명 컬럼을 하나로 병합하는 방식이다. SQL 표준에 따라 이 컬럼은 더 이상 "어느 테이블의 컬럼"이 아니므로 prefix를 붙이면 안 된다. 붙이면 ORA-25154가 발생한다. USING 컬럼은 결과셋에서도 한 번만 나타난다.

Q2NATURAL JOIN을 권장하지 않는 이유는

NATURAL JOIN은 양 테이블의 모든 동명 컬럼을 자동으로 조인 조건에 포함한다. 이후 스키마 변경으로 컬럼이 추가되면(예: created_at 같은 공통 컬럼이 양쪽에 생기면) 조인 조건이 의도와 다르게 변경되어 결과가 달라진다. 운영 환경의 안정성을 위해 ON 절 명시가 표준이다.

Q3동명 컬럼이 여러 개일 때 모범 패턴은

두 가지 원칙을 적용한다. 첫째, 모든 컬럼 참조에 alias prefix를 붙인다(e.dept_id, d.dept_id). 둘째, SELECT 리스트에서도 동명 컬럼은 alias로 재명명한다(e.dept_id AS emp_dept_id, d.dept_id AS dept_pk). 이렇게 하면 결과셋에서도 모호함이 사라지고, 이후 인라인뷰로 감쌀 때도 안전하다.

Q4서브쿼리·인라인뷰 조인 시 충돌을 막는 방법은

SELECT *를 인라인뷰 안에서 쓰지 않는다. 필요한 컬럼만 명시적으로 SELECT하고 동명이면 alias를 부여한다. 외부 쿼리에서 그 alias로만 참조하면 ORA-00918이 발생할 여지가 없다. WITH 절(CTE)을 사용하면 가독성과 디버깅이 더 쉬워진다.

Q5테이블 alias 명명 규칙 권장은

실무 통용 권장사항은 다음과 같다. 1~3자 소문자, 의미 있는 약어(employees → e, departments → d, orders → o). 같은 테이블 self-join은 e1·e2 또는 mgr·emp처럼 역할 기반 명명. 너무 짧으면 의미가 사라지고(t1·t2), 너무 길면 prefix 가독성이 떨어진다. 팀 컨벤션으로 규칙을 통일하는 게 가장 중요하다.


07 결론

ORA-00918은 조인 시 동명 컬럼에 prefix를 누락한 단순 실수에서 발생하지만, USING·NATURAL JOIN·인라인뷰·서브쿼리까지 결합되면 진단이 복잡해진다. 한 가지 습관 — 모든 컬럼 참조에 alias prefix를 붙이는 것이 가장 안전한 예방책이다.

 

실무 원칙은 다음과 같다.

 

첫째, JOIN을 사용하면 SELECT·WHERE·ORDER BY·HAVING의 모든 컬럼에 alias prefix를 붙인다.

둘째, 조인 방식은 ON 절을 기본으로 한다. NATURAL JOIN은 스키마 변경에 취약하므로 운영 환경에서 회피한다.

셋째, USING 사용 시 USING 컬럼에 prefix를 붙이지 않는다(ORA-25154 회피). USING은 단순 조회에서만 사용한다.

넷째, 인라인뷰·서브쿼리에서 SELECT *는 피하고 필요한 컬럼만 명시한다. 동명 컬럼이 있으면 alias로 재명명한다.

다섯째, 팀 컨벤션으로 테이블 alias 명명 규칙(1~3자 소문자, 의미 있는 약어)을 통일한다.

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

 

01에러 메시지의 컬럼명을 SELECT·WHERE·ORDER BY에서 찾기
02JOIN한 모든 테이블에 alias 부여 (e, d, o 형식)
03모든 컬럼 참조에 prefix 부착 (e.dept_id, d.dept_id)
04동명 컬럼 결과 노출 시 AS로 재명명 (AS emp_dept_id)
05USING 사용 시 USING 컬럼에 prefix 금지 (ORA-25154 회피)
06NATURAL JOIN 회피, ON 절 명시 표준 사용
07인라인뷰·서브쿼리에서 SELECT * 회피, 필요한 컬럼만 alias 부여

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

 

#ORA00918 #columnAmbiguouslyDefined #오라클에러 #조인컬럼모호 #JOIN #USING #ON절 #NATURALJOIN #SQL_alias #ORA25154 #ORA25155 #ORA00957 #서브쿼리 #인라인뷰 #SQL디버깅

반응형

댓글