function 검색 문장에서의 실행 횟수

3727 단어
우선 패키지를 만들고, 우리 뒤에 이 패키지를 호출해야 합니다. 계수용
CREATE OR REPLACE PACKAGE PKG_TEST IS
  ID NUMBER;
  FUNCTION GET_ID RETURN NUMBER;
  PROCEDURE SETID(V_ID NUMBER);
END PKG_TEST;
/
CREATE OR REPLACE PACKAGE BODY PKG_TEST IS
  FUNCTION GET_ID RETURN NUMBER IS
  BEGIN
    ID := ID + 1;
    RETURN ID;
  END;
  PROCEDURE SETID(V_ID NUMBER) IS
  BEGIN
    ID := V_ID;
  END;  
END;
/

우선 직접 조회
SQL> exec pkg_test.SETID(0);
PL/SQL procedure successfully completed

SQL> select pkg_test.get_id from dual group by pkg_test.get_id;
    GET_ID
----------
         1
이때 함수가 한 번 실행되었다.
SQL> exec pkg_test.SETID(0);
PL/SQL procedure successfully completed

SQL> select pkg_test.get_id from dual where pkg_test.get_id >=1 group by pkg_test.get_id;
    GET_ID
----------
         2
이때 함수는 두 번 실행되었다.
모두들 함수를 사용하면 매우 느릴 것이라는 것을 알고 있는데, 그것을 한 번 운행시킬 방법이 있습니까?
그럼요.
SQL> exec pkg_test.SETID(0);
PL/SQL procedure successfully completed

SQL> select id from (select rownum as sn,pkg_test.get_id as id from dual) where id >=0 group by id;
        ID
----------
         1

select에서 여러 번 인용해도 한 번만 실행합니다
SQL> exec pkg_test.SETID(0);
PL/SQL procedure successfully completed
SQL> select pkg_test.get_id from dual group by pkg_test.get_id;
    GET_ID
----------
         1

SQL> select pkg_test.get_id,pkg_test.get_id+1 as c2,pkg_test.get_id+2 as c3 from dual group by pkg_test.get_id;
    GET_ID         C2         C3
---------- ---------- ----------
         2          3          4

SQL> /
    GET_ID         C2         C3
---------- ---------- ----------
         3          4          5

SQL> 

일부 경우 DETERMINISTIC으로 최적화 가능
SQL> exec pkg_test.SETID(0);
PL/SQL procedure successfully completed

SQL> select pkg_test.get_id from dual connect by level <=5;
    GET_ID
----------
         1
         2
         3
         4
         5
5 rows selected

DETERMINISTIC을 추가한 후
CREATE OR REPLACE PACKAGE pkg_test IS
  id NUMBER;
  FUNCTION get_id RETURN NUMBER DETERMINISTIC;
  PROCEDURE setid(v_id NUMBER);
END pkg_test;
/
CREATE OR REPLACE PACKAGE BODY pkg_test IS
  FUNCTION get_id RETURN NUMBER DETERMINISTIC AS  
  BEGIN
    id := id + 1;
    RETURN id;
  END;
  PROCEDURE setid(v_id NUMBER) IS
  BEGIN
    id := v_id;
  END;
END;
/
SQL> select pkg_test.get_id from dual connect by level <=5;
    GET_ID
----------
         1
         1
         1
         1
         1
5 rows selected

또한 함수에는 작은 문제가 있습니다. 그룹by를 사용하지 않을 때 한 줄을 여러 번 인용하면 여러 번 실행됩니다.
SQL> SELECT pkg_test.get_id AS a, pkg_test.get_id AS b, pkg_test.get_id AS c from dual;
         A          B          C
---------- ---------- ----------
         1          2          3
1 row selected

표현식의 일부분으로 삼아도 안 돼요.
SQL> SELECT pkg_test.get_id + 0 AS a, pkg_test.get_id + 0 AS b, pkg_test.get_id + 0 AS c from dual;
         A          B          C
---------- ---------- ----------
         4          5          6
1 row selected

이런 문제에 대해서도 앞의 방법을 채택하여 조회를 한 번 끼워 넣을 수 있지만, 단지 작은 기교를 하나 더 사용해야 한다(rownum>=1)
SQL> exec pkg_test.SETID(0);
PL/SQL procedure successfully completed

SQL> SELECT id AS a, id AS b, id AS c from (SELECT pkg_test.get_id as id from dual where rownum >=1);
         A          B          C
---------- ---------- ----------
         1          1          1
1 row selected

좋은 웹페이지 즐겨찾기