2026년 06월 22일 | DBMS Error 가이드
이 글에서 다루는 내용
ORA-00960 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
ORA-00960 ambiguity in column naming in select list 는?
ORA-00960 에러는 SELECT 절에서 사용된 컬럼 별칭(alias)이 ORDER BY 절 또는 GROUP BY 절에서 참조될 때, Oracle이 해당 이름이 실제 컬럼인지 별칭인지 명확하게 구분하지 못할 때 발생합니다. 특히 SELECT 절에 정의된 컬럼 별칭이 테이블의 실제 컬럼명과 동일하거나, 조인된 여러 테이블에서 동일한 이름의 컬럼이 존재할 때 Oracle 파서가 혼란을 겪게 됩니다. 이 에러는 복잡한 다중 테이블 조인 쿼리나 서브쿼리에서 자주 등장하며, 개발 초기에는 발견되지 않다가 데이터 증가 또는 스키마 변경 이후 갑자기 나타나기도 합니다.
주요 발생 원인
1. ORDER BY 절에서 컬럼 별칭과 실제 컬럼명의 충돌
SELECT 절에서 정의한 별칭(alias)이 쿼리에 참여하는 테이블의 실제 컬럼명과 동일할 경우, Oracle은 ORDER BY 절에서 해당 이름이 컬럼을 가리키는지 별칭을 가리키는지 판단하지 못합니다. 예를 들어 salary * 1.1 AS sal처럼 별칭을 sal로 지정했는데, 조인 대상 테이블에도 sal이라는 실제 컬럼이 존재한다면 Oracle은 어떤 것을 기준으로 정렬해야 하는지 알 수 없게 됩니다. 이는 특히 레거시 코드에서 테이블 컬럼 추가 이후 갑작스럽게 발생하는 경우가 많습니다.
2. 다중 테이블 조인 시 동일한 이름의 컬럼 존재
두 개 이상의 테이블을 조인할 때 양쪽 테이블 모두에 동일한 컬럼명이 존재하고, 테이블 별칭(table alias)이나 테이블명을 명시하지 않으면 Oracle은 SELECT 절에서 어느 테이블의 컬럼을 사용해야 하는지 결정하지 못합니다. 이 상황은 NATURAL JOIN이나 USING 절 없이 단순 콤마(,) 조인을 사용할 때 특히 자주 발생합니다. 조인되는 테이블의 수가 많아질수록 이러한 모호성은 기하급수적으로 증가합니다.
3. 서브쿼리 또는 인라인 뷰에서의 컬럼 별칭 재사용
인라인 뷰(inline view) 내부에서 정의된 컬럼 별칭을 외부 쿼리의 ORDER BY나 WHERE 절에서 다시 참조할 때, 외부 쿼리의 다른 소스와 이름이 겹치면 ORA-00960이 발생할 수 있습니다. 특히 WITH 절(CTE)을 사용하는 복잡한 쿼리에서 같은 별칭을 여러 CTE 블록에서 사용하면 최종 SELECT에서 모호성이 생깁니다. 이 원인은 디버깅이 가장 까다로운 케이스 중 하나입니다.
해결 방법
원인 1 해결: 테이블 별칭(prefix)을 명시하여 모호성 제거
ORDER BY나 GROUP BY 절에서 컬럼을 참조할 때 테이블 별칭 또는 테이블명을 명시적으로 붙여주면 Oracle이 혼란 없이 해석할 수 있습니다.
-- 문제가 되는 쿼리 (ORA-00960 발생 가능)
SELECT e.employee_id,
e.salary * 1.1 AS salary -- 'salary'는 실제 컬럼명과 동일한 별칭
FROM employees e
ORDER BY salary; -- 실제 컬럼인지 별칭인지 모호
-- 해결된 쿼리: 테이블 별칭으로 실제 컬럼 명시
SELECT e.employee_id,
e.salary * 1.1 AS adjusted_salary -- 별칭을 고유하게 변경
FROM employees e
ORDER BY adjusted_salary; -- 고유한 별칭 사용으로 모호성 해소
-- 또는 컬럼 위치 번호 사용
SELECT e.employee_id,
e.salary * 1.1 AS salary
FROM employees e
ORDER BY 2; -- SELECT 절의 두 번째 컬럼 기준 정렬 (위치 참조)
원인 2 해결: 조인 쿼리에서 테이블 별칭 명시
다중 테이블 조인 시 SELECT 절의 모든 컬럼에 테이블 별칭을 반드시 붙여주어야 합니다.
-- 문제가 되는 쿼리 (ORA-00960 발생)
SELECT department_id, -- employees와 departments 양쪽에 존재하는 컬럼
employee_name,
department_name
FROM employees e,
departments d
WHERE e.department_id = d.department_id
ORDER BY department_id; -- 어느 테이블의 department_id인지 모호
-- 해결된 쿼리: 테이블 별칭으로 모든 컬럼 한정
SELECT e.department_id, -- 테이블 별칭 명시
e.employee_name,
d.department_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id
ORDER BY e.department_id; -- 명확하게 employees 테이블의 컬럼 지정
-- ANSI JOIN 방식으로 변경하여 가독성과 명확성 동시 향상
SELECT e.employee_id,
e.first_name || ' ' || e.last_name AS full_name,
d.department_name,
e.salary
FROM employees e
INNER JOIN departments d ON e.department_id = d.department_id
INNER JOIN locations l ON d.location_id = l.location_id
ORDER BY e.salary DESC, e.employee_id ASC;
원인 3 해결: 서브쿼리 및 CTE에서 고유한 별칭 사용
-- 문제가 되는 CTE 쿼리
WITH dept_summary AS (
SELECT department_id,
AVG(salary) AS avg_sal,
COUNT(*) AS cnt
FROM employees
GROUP BY department_id
),
emp_detail AS (
SELECT employee_id,
department_id,
salary,
salary / AVG(salary) OVER (PARTITION BY department_id) AS avg_sal
-- avg_sal이 dept_summary와 동일하여 충돌 가능
FROM employees
)
SELECT d.department_id,
d.avg_sal, -- 어느 CTE의 avg_sal인지 모호할 수 있음
e.avg_sal
FROM dept_summary d
JOIN emp_detail e ON d.department_id = e.department_id
ORDER BY avg_sal; -- ORA-00960 발생!
-- 해결된 쿼리: CTE 별칭을 고유하게 구분
WITH dept_summary AS (
SELECT department_id,
AVG(salary) AS dept_avg_salary, -- 고유한 별칭
COUNT(*) AS dept_emp_count
FROM employees
GROUP BY department_id
),
emp_detail AS (
SELECT employee_id,
department_id,
salary,
salary / AVG(salary) OVER (PARTITION BY department_id) AS emp_salary_ratio
-- 고유한 별칭 사용
FROM employees
)
SELECT d.department_id,
d.dept_avg_salary,
e.emp_salary_ratio
FROM dept_summary d
JOIN emp_detail e ON d.department_id = e.department_id
ORDER BY d.dept_avg_salary DESC; -- 명확하게 CTE와 컬럼 지정
예방 방법
1. 컬럼 별칭은 항상 고유하고 의미 있는 이름으로 지정하라
SELECT 절에서 컬럼 별칭을 정의할 때 해당 쿼리에 참여하는 모든 테이블의 실제 컬럼명과 겹치지 않도록 네이밍 컨벤션을 수립하세요. 예를 들어 계산된 컬럼에는 _calc, _formatted, _ratio 같은 접미사를 붙이거나, 집계 결과에는 total_, avg_, cnt_ 같은 접두사를 붙이는 규칙을 팀 전체에 적용하면 ORA-00960뿐 아니라 코드 가독성도 크게 향상됩니다. 코드 리뷰 시 체크리스트에 “별칭 고유성 확인” 항목을 추가하는 것도 좋은 방법입니다.
2. 모든 SELECT 쿼리에서 테이블 별칭을 필수로 사용하는 코딩 표준을 수립하라
단일 테이블 쿼리라도 항상 테이블 별칭을 붙이는 습관을 들이면, 나중에 조인이 추가될 때 발생할 수 있는 ORA-00960을 사전에 차단할 수 있습니다. 팀의 SQL 코딩 표준 문서에 “모든 컬럼 참조 시 테이블 별칭 필수”를 명문화하고, SQL*Plus나 SQL Developer의 포매팅 도구 또는 정적 분석 도구(예: SQLFluff, PL/SQL Analyzer)를 CI/CD 파이프라인에 통합하여 자동으로 검사하도록 구성하면 실수를 사전에 방지할 수 있습니다.
관련 에러
- ORA-00918:
column ambiguously defined— ORA-00960과 매우 유사한 에러로, SELECT 절이 아닌 WHERE 절이나 JOIN 조건에서 테이블 한정자 없이 중복된 컬럼명을 사용할 때 발생합니다. 두 에러 모두 테이블 별칭을 명시하는 것으로 해결됩니다. - ORA-00957:
duplicate column name— CREATE TABLE 또는 SELECT INTO 구문에서 동일한 이름의 컬럼이 두 번 정의될 때 발생하며, ORA-00960의 근본적인 원인 중 하나가 될 수 있습니다. - ORA-01748:
only simple column names allowed here— CONNECT BY 절이나 특정 DDL 구문에서 한정자(qualifier)가 허용되지 않는 위치에table.column형태로 컬럼을 참조할 때 발생합니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.