2016-09-09 5 views
1

일부 매개 변수를 사용하여 webservice를 호출하고 응답을 구문 분석 한 다음 값을 반환하는 PL/SQL 함수를 작성했습니다. 그것은 아주 잘 작동합니다.PL/SQL 함수의 INSERT 문

그러나 응답이 느려질 수 있습니다. 매개 변수는 일반적으로 모든 가능한 값의 매우 작은 하위 집합이므로 테이블에 응답을 캐시 할 생각이 있습니다. 기능은 내가이 기능을 시도한 다음

CREATE OR REPLACE FUNCTION myfct(p1 IN VARCHAR2, p2 IN VARCHAR2) 
RETURN VARCHAR2 
IS 
    cache_hit NUMBER ; 
    res VARCHAR2(200) ; 
BEGIN 
    SELECT COUNT(*) INTO cache_hit FROM MYCACHE WHERE param1 = p1 AND param2 = p2 ; 

    IF(cache_hit = 1) 
    THEN 
     SELECT MYCACHE.result INTO res FROM MYCACHE WHERE param1 = p1 AND param2 = p2 ; 

     RETURN res ; 
    END IF ; 

    -- complex operations 
    res := p1 || p2 ; 


    INSERT INTO MYCACHE(param1, param2, result) VALUES(p1, p2, res) ; 

    RETURN res ; 
END ; 

과 같습니다

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

절차에 DML 부분을 포장하려고 : 나는 오류가 발생했습니다

SELECT myfct('ABC', 'DEF') FROM DUAL ; 

을 함수에서이 프로 시저를 호출하면 도움이되지 않습니다.

나는 PRAGMA AUTONOMOUS_TRANSACTION와 해결 방법 발견하고 COMMIT :

CREATE OR REPLACE FUNCTION myfct(p1 IN VARCHAR2, p2 IN VARCHAR2) 
RETURN VARCHAR2 
IS 
    PRAGMA AUTONOMOUS_TRANSACTION; 
    cache_hit NUMBER ; 
    res VARCHAR2(200) ; 
BEGIN 
    SELECT COUNT(*) INTO cache_hit FROM MYCACHE WHERE param1 = p1 AND param2 = p2 ; 

    IF(cache_hit = 1) 
    THEN 
     SELECT MYCACHE.result INTO res FROM MYCACHE WHERE param1 = p1 AND param2 = p2 ; 

     RETURN res ; 
    END IF ; 

    -- complex operations 
    res := p1 || p2 ; 


    INSERT INTO MYCACHE(param1, param2, result) VALUES(p1, p2, res) ; 

    COMMIT ; 
    RETURN res ; 
END ; 

을하지만 정말 좋은 생각입니다 있는지 궁금해. 이 해결 방법을 언급하는 사람들은 이유를 정확하게 말하지 않고도 위험 할 수 있다고 말했습니다.

내 기능은 PRAGMA AUTONOMOUS_TRANSACTION에 대한 좋은 사용의 예입니까, 아니면 내가 원하는 것을하기위한 더 좋고 안전한 방법입니까?

+0

PL/SQL에서 함수를 사용하여 select를 사용하면 결과를 일부 전역 콜렉션에 저장 한 후 테이블에 값을 삽입하는 것이 더 나을 수 있습니다. – SkyWalker

+0

나는 그것에 대해 생각했지만 모든 가능한 조합으로, 우리는 몇 백만 행을 저장할 것이고, 우리는 ~ 10 000 combinaisons만을 정기적으로 사용할 계획이다. 캐시 테이블이있는이 하이브리드 솔루션을 사용하면 모든 조합에 응답 할 수 있지만 가장 적절한 조합 만 저장할 수 있습니다. –

+0

결과를 최신 상태로 유지할 수 있습니까? 복잡한 선택의 기본 데이터가 변경되면 어떻게됩니까? 어쩌면 당신은'materialized view '로 당신의 퍼포먼스 문제를 해결할 수 있을까? –

답변

3

SQL 컨텍스트에서 어떤 종류의 PL/SQL 함수를 호출 할 수 있는지 제한되어 있습니다. SQL 컨텍스트에서 대신 PL/SQL 컨텍스트에서 PL/SQL 함수를 호출하지 말고 모두가 잘되어야합니다 :

declare 
    v_foo constant varchar2(32767) := myfct('foo', 'bar'); 
begin 
    dbmsn_output.put_line(v_foo); 
end; 

을 그러나 당신이 오라클 네이티브 PL/SQL Function Result Cache -FEATURE 자신의 캐시를 고려하시기 바랍니다 구현하기 전에 :

PL/SQL 함수 결과 캐싱 메커니즘은 응용 프로그램을 실행하는 모든 세션에서 사용할 수있는 공유 전역 영역 (SGA)에서 PL/SQL 함수의 결과를 캐시하기 위해 언어 지원 및 시스템 관리 방법을 제공합니다. 캐싱 메커니즘은 효율적이고 사용하기 쉽고 자신의 캐시와 캐시 관리 정책을 설계하고 개발하는 부담을 덜어줍니다.

결과 캐시 된 함수가 호출 될 때 시스템은 캐시를 확인합니다. 캐시에 동일한 매개 변수 값이있는 함수를 이전에 호출 한 결과가 들어 있으면 시스템은 캐시 된 결과를 호출자에게 리턴하고 함수 본문을 재실행하지 않습니다. 캐시에 결과가 포함되어 있지 않으면 시스템은 함수 본문을 실행하고 호출자에게 제어를 반환하기 전에 캐시에 결과 (이 매개 변수 값에 대한)를 추가합니다.

0

규칙 및 좋은 소프트웨어 디자인에 따라 함수는 데이터베이스를 변경하면 안되며 값만 반환해야합니다. 대신 프로 시저를 사용하십시오. 이 때문에 PLSQL과 C와 같은 함수가 둘 다 존재합니다. 이는 주로 많은 사람들이 문체로 간주합니다. 그러나 나는 당신이 그들의 용도를 분리하여 유지할 것을 강력하게 제안한다.