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는 열이름이 같다라고 판단한듯 하다..
'DB > ORACLE' 카테고리의 다른 글
[오라클] DB 관리 체크 항목 (0) | 2023.07.31 |
---|---|
[오라클] 해당 스키마에 존재하는 DB 링크를 조회 (0) | 2023.03.28 |
[Oracle - PL_SQL] 오라클 FUNCTION GOTO 사용하기 (0) | 2022.09.26 |
[Oracle - PL_SQL] 오라클 FUNCTION, PROCEDURE EXCEPTION 활용법 (0) | 2022.09.26 |
[Oracle - PL_SQL] 오라클 FUNCTION LOOP 사용법 (0) | 2022.09.26 |