Oracle ORA-01730 오류 원인과 해결 방법 완벽 가이드

ORA-01730
2026년 07월 28일 | DBMS Error 가이드

이 글에서 다루는 내용

ORA-01730 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.

ORA-01730 invalid number of column names specified 는?

ORA-01730 에러는 뷰(View)를 생성할 때 지정한 컬럼 이름의 수가 SELECT 절에서 반환하는 컬럼의 수와 일치하지 않을 때 발생합니다. Oracle은 뷰 정의 시 별칭(alias) 컬럼 목록을 명시적으로 선언할 수 있는데, 이 목록의 개수와 실제 쿼리의 결과 컬럼 개수가 다르면 이 에러를 발생시킵니다. 주로 CREATE VIEW view_name (col1, col2, ...) 형태로 뷰를 생성할 때 괄호 안의 컬럼 개수를 잘못 지정하는 경우에 빈번히 발생합니다.


주요 발생 원인

1. CREATE VIEW 시 컬럼 별칭 개수와 SELECT 절 컬럼 개수 불일치

가장 흔한 원인입니다. 뷰를 생성할 때 뷰 이름 뒤에 컬럼 별칭 목록을 괄호로 묶어 정의하는데, 이 별칭의 수가 SELECT 문이 반환하는 컬럼 수와 다를 경우 에러가 발생합니다. 예를 들어, SELECT 절에서 5개의 컬럼을 반환하는데 뷰 정의에 4개의 컬럼 이름만 지정했을 경우 Oracle은 즉시 ORA-01730을 반환합니다.

2. 뷰 수정(ALTER/REPLACE) 시 컬럼 구조 변경 누락

기존 뷰를 CREATE OR REPLACE VIEW 구문으로 수정할 때, SELECT 절에 새로운 컬럼을 추가했지만 뷰 헤더의 컬럼 별칭 목록을 업데이트하지 않는 경우에 발생합니다. 실무에서 테이블 구조가 변경되어 뷰를 재작성할 때 자주 발생하는 패턴입니다. 특히 여러 명의 개발자가 동시에 뷰를 관리할 때 이러한 불일치가 발생하기 쉽습니다.

3. 동적 SQL 또는 스크립트 자동 생성 과정에서의 오류

애플리케이션 코드나 배치 스크립트에서 동적으로 CREATE VIEW 문을 생성할 때, 컬럼 별칭 목록을 생성하는 로직과 SELECT 절을 생성하는 로직이 서로 동기화되지 않아 불일치가 발생할 수 있습니다. 특히 컬럼 목록을 반복문으로 동적 생성하는 경우, 조건 분기에 따라 컬럼이 추가되거나 제외될 때 두 목록의 수가 달라지는 문제가 생깁니다.


해결 방법

원인 1 해결: 컬럼 별칭 수를 SELECT 절과 맞추기

잘못된 예시:

-- 오류 발생: 뷰 컬럼 별칭은 3개인데 SELECT 절은 4개 컬럼 반환
CREATE VIEW emp_view (emp_id, emp_name, dept_name)
AS
SELECT e.employee_id,
       e.first_name || ' ' || e.last_name,
       d.department_name,
       e.salary   -- 4번째 컬럼인데 별칭 목록에는 없음
FROM   employees e
JOIN   departments d ON e.department_id = d.department_id;
-- ORA-01730: invalid number of column names specified

올바른 예시:

-- 수정: 뷰 컬럼 별칭을 4개로 맞춤
CREATE VIEW emp_view (emp_id, emp_name, dept_name, salary)
AS
SELECT e.employee_id,
       e.first_name || ' ' || e.last_name,
       d.department_name,
       e.salary
FROM   employees e
JOIN   departments d ON e.department_id = d.department_id;

또는 뷰 헤더에 컬럼 목록을 명시하지 않고 SELECT 절에서 별칭을 직접 지정하는 방법도 있습니다:

-- SELECT 절에서 직접 별칭 지정 (뷰 헤더 컬럼 목록 생략)
CREATE VIEW emp_view
AS
SELECT e.employee_id                        AS emp_id,
       e.first_name || ' ' || e.last_name   AS emp_name,
       d.department_name                    AS dept_name,
       e.salary                             AS salary
FROM   employees e
JOIN   departments d ON e.department_id = d.department_id;

원인 2 해결: CREATE OR REPLACE 시 컬럼 목록 동기화

-- 기존 뷰 (컬럼 3개)
CREATE OR REPLACE VIEW sales_summary (region, total_sales, sale_count)
AS
SELECT region,
       SUM(amount),
       COUNT(*)
FROM   sales
GROUP BY region;

-- 테이블에 새 컬럼(avg_amount) 추가 후 뷰 수정 시 헤더도 함께 수정
CREATE OR REPLACE VIEW sales_summary (region, total_sales, sale_count, avg_amount)
AS
SELECT region,
       SUM(amount),
       COUNT(*),
       AVG(amount)   -- 새로 추가된 컬럼
FROM   sales
GROUP BY region;

현재 뷰의 컬럼 구조를 확인하려면 다음 쿼리를 사용하세요:

-- 뷰 컬럼 정보 조회
SELECT column_name,
       column_id,
       data_type,
       nullable
FROM   user_tab_columns
WHERE  table_name = 'SALES_SUMMARY'
ORDER BY column_id;

-- 뷰 정의 텍스트 확인
SELECT text
FROM   user_views
WHERE  view_name = 'SALES_SUMMARY';

원인 3 해결: 동적 SQL에서 컬럼 개수 검증 로직 추가

-- 동적 뷰 생성 시 컬럼 개수를 검증하는 PL/SQL 예시
DECLARE
    v_col_list    VARCHAR2(4000) := 'col_a, col_b, col_c';
    v_select_list VARCHAR2(4000) := 'a.col_a, b.col_b, c.col_c';
    v_col_count   NUMBER;
    v_sel_count   NUMBER;
    v_sql         VARCHAR2(4000);
BEGIN
    -- 컬럼 별칭 개수 계산 (쉼표 수 + 1)
    v_col_count := LENGTH(v_col_list) 
                   - LENGTH(REPLACE(v_col_list, ',', '')) + 1;
    v_sel_count := LENGTH(v_select_list) 
                   - LENGTH(REPLACE(v_select_list, ',', '')) + 1;

    -- 개수 불일치 시 에러 처리
    IF v_col_count != v_sel_count THEN
        RAISE_APPLICATION_ERROR(-20001,
            'View column count mismatch: header=' || v_col_count 
            || ', select=' || v_sel_count);
    END IF;

    -- 검증 통과 후 뷰 생성
    v_sql := 'CREATE OR REPLACE VIEW dynamic_view (' 
             || v_col_list || ') AS SELECT ' 
             || v_select_list 
             || ' FROM table_a a, table_b b, table_c c'
             || ' WHERE a.id = b.id AND b.id = c.id';

    EXECUTE IMMEDIATE v_sql;
    DBMS_OUTPUT.PUT_LINE('View created successfully.');

EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('Error: ' || SQLERRM);
        RAISE;
END;
/

예방 방법

1. 뷰 생성 시 헤더 컬럼 목록 생략하고 SELECT 절 별칭만 사용

뷰 헤더에 컬럼 이름 목록을 명시하는 방식 대신, SELECT 절 내에서 각 컬럼에 AS alias_name 형태로 별칭을 직접 지정하는 습관을 들이세요. 이렇게 하면 컬럼 목록과 SELECT 절 간의 불일치 자체가 발생하지 않아 ORA-01730 에러를 원천 차단할 수 있습니다. 단, 표현식이나 집계 함수처럼 컬럼명을 자동으로 결정할 수 없는 경우에는 반드시 별칭을 지정해야 합니다.

-- 권장 방식: SELECT 절에서 직접 별칭 지정
CREATE OR REPLACE VIEW dept_salary_view AS
SELECT d.department_id                  AS dept_id,
       d.department_name                AS dept_name,
       COUNT(e.employee_id)             AS emp_count,
       ROUND(AVG(e.salary), 2)          AS avg_salary,
       MAX(e.salary)                    AS max_salary
FROM   departments d
LEFT JOIN employees e ON d.department_id = e.department_id
GROUP BY d.department_id, d.department_name;

2. 뷰 DDL 변경 전 컬럼 수 검증 쿼리 실행을 개발 표준으로 채택

뷰를 생성하거나 수정하기 전에 반드시 SELECT 절 단독으로 실행하여 반환 컬럼 수를 확인하는 절차를 팀 개발 표준으로 정착시키세요. CI/CD 파이프라인에 뷰 DDL 검증 단계를 추가하거나, 코드 리뷰 체크리스트에 뷰 컬럼 수 일치 여부를 포함하는 것도 효과적입니다.

-- 배포 전 컬럼 수 점검용 쿼리
SELECT COUNT(*) AS column_count
FROM   (
    -- 실제 뷰에 사용할 SELECT 문 붙여넣기
    SELECT d.department_id,
           d.department_name,
           COUNT(e.employee_id),
           ROUND(AVG(e.salary), 2),
           MAX(e.salary)
    FROM   departments d
    LEFT JOIN employees e ON d.department_id = e.department_id
    GROUP BY d.department_id, d.department_name
)
WHERE  ROWNUM = 1;

관련 에러

  • ORA-00957: duplicate column name — 뷰 정의에서 중복된 컬럼 이름을 사용할 때 발생하며, ORA-01730과 함께 뷰 생성 시 자주 마주치는 에러입니다.
  • ORA-01741: illegal zero-length identifier — 컬럼 별칭을 공백이나 빈 문자열로 지정할 때 발생합니다.
  • ORA-00998: must name this expression with a column alias — 표현식이나 함수를 포함한 컬럼에 별칭을 지정하지 않고 뷰를 생성할 때 발생하며, ORA-01730을 피하기 위해 뷰 헤더를 생략했을 때 함께 접하게 되는 에러입니다.
  • ORA-04063: view has errors — 뷰가 무효화(INVALID) 상태가 되었을 때 발생하며, 기반 테이블 구조 변경 후 뷰를 재컴파일하지 않으면 발생합니다.
DBMS 에러 코드 시리즈

주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.

본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.

댓글 남기기