DB/ORACLE

[Oracle - 에러] ORACLE INSERT FETCH ROWS 시 ORA-00918 오류

Kang_hobin 2022. 12. 22. 11:08

PL/SQL: ORA-00918: 열의 정의가 애매합니다

동료 개발자분이 프로시저의 insert 구문 중 작성하던 중 ORA-00918 에러가 발생했다.

쿼리는 아래와 같았다.

INSERT INTO TABLE_1
(
       COL1
     , COL2
     , COL3
     , COL4
     , FRST_REG_DT
     , FRST_RGTR_DSTN_NO
     , FRST_REG_IP
     , CHG_REG_DT 
     , CHG_RGTR_DSTN_NO 
     , CHG_REG_IP 
)
SELECT P_PROCEDURE_PARAM_1 -- 프로시저 입력 변수 1
     , P_PROCEDURE_PARAM_2 -- 프로시저 입력 변수 2
     , T.COL1
     , T.COL2
     , SYSDATE
     , P_PROCEDURE_PARAM_3 -- 프로시저 입력 변수 3
     , P_PROCEDURE_PARAM_4 -- 프로시저 입력 변수 4
     , SYSDATE
     , P_PROCEDURE_PARAM_3 -- 프로시저 입력 변수 3
     , P_PROCEDURE_PARAM_4 -- 프로시저 입력 변수 4
  FROM TABLE_2 T
 WHERE (~~ 조건 1) 
   AND (~~ 조건 2) 
 ORDER BY DBMS_RANDOM.RANDOM()
 FETCH FIRST 3 ROWS ONLY;

위 쿼리의 특징을 보면

1. SELECT절에 프로시저 입력 변수 1,2,3,4를 사용하고, 

2. ORDER BY DBMS_RAMDOM.RANDOM(); 구문을 통해 TABLE_2의 조회 순서를 매번 랜덤으로 변경하며

3. FETCH FIRST 3 ROWS ONLY 구문으로 최초 3개의 로우만 셀렉트 하여 

4. TABLE_1에 INSERT 한다.

였는데.. 위와 같은 쿼리를 실행하면 INSERT 위치에서 PL/SQL: ORA-00918: 열의 정의가 애매합니다 오류가 발생했다.

계속 구글링을 하던 중 아래 stackoverflow에서 해법을 찾았다.

 

참고 : https://stackoverflow.com/questions/68446930/insert-select-not-working-with-fetch-next-x-rows

참고한 부분을 요약하면 아래와 같다.


ORA-00918with the 절의 가장 일반적인 원인은 FETCH선택 목록의 어떤 변수도 같은 이름을 가질 수 없다는 경고입니다. 예를 들어 다음 SELECT은 합법적입니다.

SELECT object_type, object_name, object_name
FROM   dba_objects
WHERE OBJECT_NAME LIKE 'USER%'
ORDER BY 1, 2

.. 그리고 이것은 ...

SELECT object_type, object_name, object_name
FROM   dba_objects
WHERE OBJECT_NAME LIKE 'USER%'
ORDER BY 1, 2
OFFSET 0 ROWS
FETCH NEXT 5 ROWS ONLY;

 


결론은 FETCH선택 목록의 어떤 변수도 같은 이름을 가질 수 없다였다.

SELECT 쿼리에서 대체 어디부분이 문제였는가.. 했더니 설마 설마 했던 프로시저 IN PARAMETER 였다.

파라미터를 같은 것을 가져다가 쓰고, 그걸 FETCH 하여 3개 로우만 가져오려다 보니 라미터가 같은 것끼리 같은 열 이름으로 판단하여 중복 열이름 오류가 발생한 거였다..

따라서 변경한 쿼리는 아래와 같다.

INSERT INTO TABLE_1
(
       COL1
     , COL2
     , COL3
     , COL4
     , FRST_REG_DT
     , FRST_RGTR_DSTN_NO
     , FRST_REG_IP
     , CHG_REG_DT 
     , CHG_RGTR_DSTN_NO 
     , CHG_REG_IP 
)
SELECT P_PROCEDURE_PARAM_1
     , P_PROCEDURE_PARAM_2
     , T.COL1
     , T.COL2
     , SYSDATE AS FRST_REG_DT -- 열 이름 직접 지정
     , P_PROCEDURE_PARAM_3 AS FRST_RGTR_DSTN_NO -- 열 이름 직접 지정
     , P_PROCEDURE_PARAM_4 AS FRST_REG_IP -- 열 이름 직접 지정
     , SYSDATE AS CHG_REG_DT -- 열 이름 직접 지정
     , P_PROCEDURE_PARAM_3 AS CHG_RGTR_DSTN_NO -- 열 이름 직접 지정
     , P_PROCEDURE_PARAM_4 AS CHG_REG_IP -- 열 이름 직접 지정
  FROM TABLE_2 T 
 WHERE (~~ 조건 1) 
   AND (~~ 조건 2) 
 ORDER BY DBMS_RANDOM.RANDOM()
 FETCH FIRST 3 ROWS ONLY;

 

파라미터 변수도 상수로 받아들일텐데, 결국 오라클은 상수도 열 이름으로 받아들이고, FETCH는 열이름이 같다라고 판단한듯 하다..