ORA-14551: 질의 안에 DML 작업을 수행할 수 없습니다. (ORA-14551: cannot perform a DML operation inside a query)

ORA-14551: cannot perform a DML operation inside a query 오류가 발생하였나요? 우선 해당 오류에 대한 직설적인 해석을 시도해 봅시다~ 질의 안에 DML 작업이라...? DML이 무엇인지 알아야겠지요?

ORA-14551: 질의 안에 DML 작업을 수행할 수 없습니다.

ORA-14551 질의 안에 DML 작업을 수행할 수 없습니다
  • 데이터 정의 언어 (DDL : Data Definition Language)
  • 데이터 조작 언어 (DML : Data Manipulation Language)
  • 데이터 제어 언어 (DCL : Date Control Language)
  • 트랜잭션 제어 언어 (TCL : Transaction Control Language)

DML은 바로 데이터 조작 언어를 뜻하며, 해당 오류와 관련하여 가장 흔하게 발생하는 대표적인 명령어는 INSERT, UPDATE, DELETE가 있습니다. 데이터의 삽입, 수정, 삭제를 통해 조작하는 언어를 의미하는 것이랍니다.

그렇다면, 쿼리 안에서 해당과 같은 데이터 조작이 이루어졌기에 'ORA-14551: 질의 안에 DML 작업을 수행할 수 없습니다.' 오류가 발생한 것일 겁니다.

예를 들면, 펑션을 생각해 봅시다. 펑션은 오라클에서 매개변수를 입력받아 값을 반환하는 함수를 뜻합니다. 다음과 같이 함수가 있다고 가정해 봅시다.

  • P_V 라는 매개변수를 받아 VARCHAR2 형태로 반환하는 함수입니다.
  • 반환값은 테스트 차원에서 항상 NULL로 하도록 임의처리하겠습니다.
  • 함수 내부에서 DML이 이루어지는 특징이 있습니다.

CREATE OR REPLACE FUNCTION FUNCTION_NAME (P_V IN VARCHAR2)
   RETURN VARCHAR2
IS
BEGIN
   INSERT INTO TABLE_NAME (COLUMN_NAME)
        VALUES (P_V);

   UPDATE TABLE_NAME
      SET COLUMN_NAME = P_V;

   DELETE FROM TABLE_NAME;

   RETURN NULL;
END FUNCTION_NAME;
/

이때, FUNCTION_NAME 펑션을 한 번 실행해 보겠습니다. 다음과 같은 오류를 맞이할 것입니다.

SELECT FUNCTION_NAME (0) FROM DUAL;
ERROR at line 1:
ORA-14551: cannot perform a DML operation inside a query
ORA-06512: at "USER_NAME.FUNCTION_NAME", line 1

ORA-14551: cannot perform a DML operation inside a query

해결 방법으로는 2가지가 있는데,
첫 번째는 질의 안에서 DML의 필요 여부를 재검토하는 것입니다. 의미 없는 DML이라면 정리하는 방향으로 하면 될 것입니다.
두 번째는 프라그마(AUTONOMOUS_TRANSACTION)를 활용하여 펑션 등의 객체 질의 안에서 커밋이나 롤백을 진행하는 것입니다.
다음은 프라그마 사용 예제이며, 특이사항은 다음과 같습니다.

  • PRAGMA AUTONOMOUS_TRANSACTION;
  • COMMIT;
CREATE OR REPLACE FUNCTION FUNCTION_NAME (P_V IN VARCHAR2)
   RETURN VARCHAR2
IS
   PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
   INSERT INTO TABLE_NAME (COLUMN_NAME)
        VALUES (P_V);

   UPDATE TABLE_NAME
      SET COLUMN_NAME = P_V;

   DELETE FROM TABLE_NAME;

   COMMIT;

   RETURN NULL;
END FUNCTION_NAME;
/

위와 같은 프라그마를 구성하였을 때, 펑션을 호출하면 정상적으로 실행을 합니다. 물론 내부 커밋이 있기에 사용 시에 주의가 필요하다는 점을 꼭 알고 가셔야 합니다. 일반적으로 펑션이라 함은 앞에서 설명드렸듯이 매개변수를 입력하여 반환값을 확인하는 것인데, 내부적으로 DML이 작동한다는 것을 예상하기는 힘들기 때문입니다. 이는 문제가 발생하였을 때, 유지보수비용의 증대를 불러올 수 있답니다. 문제가 발생하여 '값이 도대체 어디서 바뀌는 거지?' 하고 찾아보았는데 설마 펑션 내부에서 그러한 동작이 있으리라고는 생각하기 힘들어서 찾는 데 시간이 많이 소요된답니다...

댓글 쓰기
가져가실 때, 출처 표시 부탁드려요! 감사합니다. 💗