쿼리 내에서 DML 작업을 수행할 수 없습니다.
오라클 기능 내부, 특히 커서 루프 내부에서 DML 연산을 추가할 수 없는 이유를 납득할 수 없습니다.저는 오라클이 커서 루프 내에서 DML 연산을 지원하지 않는다고 생각합니다.
커서 루프 안의 테이블에 삽입해야 하는 경우 어떻게 합니까?그 안에 새로운 스토어 프로시저를 만들거나 다른 것을 만들겠습니까?
오류 메시지 : 쿼리 내에서 DML 작업을 수행할 수 없습니다.
여기 제 기능이 있습니다.
CREATE OR REPLACE FUNCTION TEST_FUNC(U_ID IN VARCHAR2)
RETURN VARCHAR2
IS
V_MESSAGE VARCHAR2(30);
CURSOR C_PERSON (V_ID VARCHAR2) IS
SELECT NAME_UPPER
FROM TBL_PERSON
WHERE NAME_UPPER = V_ID;
BEGIN
FOR C_PERSON_CURSOR IN C_PERSON(U_ID)
LOOP
INSERT INTO TMP_PERSON(NAME) VALUES (C_PERSON_CURSOR.NAME_UPPER);
END LOOP;
RETURN V_MESSAGE;
EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;
PL/SQL 함수 안에서 DML을 사용할 수 있습니다. 문제 없습니다.그러나 함수는 SQL이 아닌 PL/SQL에서만 호출할 수 있습니다. 즉, 다음과 같이 호출할 수 있습니다.
declare
l_message varchar2(30);
begin
l_message := test_func('123');
end;
... 이와 같이는 안됩니다.
select test_func(empno) from emp;
그것은 당신이 올린 오류 메시지로 이어집니다.
저를 포함한 많은 사람들이 이와 같이 '부작용'이 있는 기능을 좋아하지 않지만, 그것은 기술적인 문제가 아니라 모범 사례와 기준의 문제입니다.
Oracle PL/SQL 함수 내에서 DML 작업을 수행할 수 있으며 일반적으로 좋은 방법은 아니지만 SQL에서 DML 작업을 호출할 수 있습니다.함수는 프래그마로 표시되어야 합니다.AUTONOMOUS_TRANSACTION
그리고 이 함수를 종료하기 전에 트랜잭션을 커밋하거나 롤백해야 합니다(ANAUNOUS_TRANSATION Pragma 참조).
SQL에서 호출되는 이러한 종류의 함수는 쿼리 성능을 크게 저하시킬 수 있음을 알아야 합니다.감사용으로만 사용하는 것을 추천합니다.
사용자 기능에서 시작하는 스크립트의 예는 다음과 같습니다.
테이블 TBL_PERSORE 생성(NAME_UPER VARCHAR2(30)); 테이블 TMP_Person 생성(NAME VARCHAR2(30)); TBL_Person(NAME_UPER) 값에 삽입('KING'); 함수 테스트 생성 또는 교체_FUNC(VARCHAR2의 U_ID)반환 VARCHAR2IS프라그마 자율_Transaction; -- SQL에서 호출 필요 V_MESSAGE VARCHAR2(2000);커서 C_Person(V_ID VARCHAR2) ISSELECT NAME_UPERFROM TBL_PersonWHERE NAME_UPER =V_ID;시작한다.FORC_Person_CURSER Inc_Person(U_ID)고리TMP_Person(NAME) 값에 삽입(C_Person_Cursor)합니다.NAME_UPER); V_MESSAGE := SQL%ROWCOUNT|| 'TMP_Person 테이블에 성공적으로 삽입된 인물 기록';엔드 루프; COMIT; -- 현재 자율 트랜잭션을 커밋해야 합니다.-- 기능을 종료하기 전에 실행할 수 있습니다. 리턴 V_MESSAGE; 예외.그때 다른 사람들이롤백;raise_application_error(-20001, '오류가 발생했습니다 - '|SQLCODE|' -ERROR- '|SQLERRM);끝;/ 프롬프트 TEST_FUNC 기능을 호출하고 TMP_Person 테이블에 새 레코드를 삽입합니다.듀얼에서 TEST_FUNC('KING')를 선택합니다; PROMCT TMP_Person 테이블 내용A30의 색상 이름선택 * TMP_Person;
이전 스크립트를 실행하면 다음과 같은 출력을 얻을 수 있습니다.
테이블 생성. 테이블 생성. 1행 생성. 함수가 생성되었습니다. TEST_FUNC 기능 호출 및 TMP_Person 테이블에 새 레코드 삽입 TEST_FUNC('킹')------------------------------------------------------------1 개인 레코드를 TMP_Person 테이블에 성공적으로 삽입함 TMP_Person 테이블의 내용 이름.------------------------------왕
언급URL : https://stackoverflow.com/questions/4095060/cannot-perform-dml-operation-inside-a-query
'itsource' 카테고리의 다른 글
PowerShell로 특정 시간 이상 된 파일인지 확인하려면 어떻게 해야 합니까? (0) | 2023.10.29 |
---|---|
엑셀 시트가 TFS에서 생성되었다는 것을 잊게 하려면 어떻게 해야 합니까? (0) | 2023.10.24 |
아이폰 애플리케이션에서 비밀번호 필드의 텍스트를 어떻게 모호하게 합니까? (0) | 2023.10.24 |
mysql 설명서를 읽는 것이 mariadb 개념을 배우는 좋은 방법입니까? (0) | 2023.10.24 |
다중 스타일링 디브로 php를 루프하는 방법 (0) | 2023.10.24 |