programing

Oracle 12에 SQL의 로컬 수집 유형에 문제가 있습니까?

cafebook 2023. 8. 1. 20:48
반응형

Oracle 12에 SQL의 로컬 수집 유형에 문제가 있습니까?

간단히 말해서, 아래에 보이는 코드에 대해 논의할 것을 제안합니다.

실행 시:

  • Oracle 11 컴파일러의 성능 향상

    "PLS-00306: 'PIP_TABLE' 호출 시 잘못된 숫자 또는 인수 유형 팁"

    "PLS-00642: SQL 문에서 허용되지 않는 로컬 컬렉션 유형"

  • Oracle 12는 이러한 경고 없이 다음 패키지를 컴파일하지만 런타임에 깜짝 놀라게 됩니다.

    익명 블록을 그대로 실행할 때 - 모든 것이 좋습니다(우리는 일부 행을 파이프로 연결할 수 있습니다).pipe_table함수 - 영향을 미치지 않음)

    이제 선을 주석을 달겠습니다.hello;또는 절차에 대한 호출을 하고 변경된 익명 블록을 다시 실행하면 "ORA-22163: 왼쪽과 오른쪽 컬렉션이 동일한 유형이 아닙니다."라는 메시지가 표시됩니다.

문제는 Oracle 12가 SQL에서 로컬 수집 유형을 허용하느냐는 질문입니다.그렇다면 코드에 문제가 있습니까?PACKAGE buggy_report?

CREATE OR REPLACE PACKAGE buggy_report IS

  SUBTYPE t_id IS NUMBER(10);
  TYPE t_id_table IS TABLE OF t_id;

  TYPE t_info_rec IS RECORD ( first NUMBER );
  TYPE t_info_table IS TABLE OF t_info_rec;
  TYPE t_info_cur IS REF CURSOR RETURN t_info_rec;

  FUNCTION pipe_table(p t_id_table) RETURN t_info_table PIPELINED;

  FUNCTION get_cursor RETURN t_info_cur;

END buggy_report;
/

CREATE OR REPLACE PACKAGE BODY buggy_report IS

  FUNCTION pipe_table(p t_id_table) RETURN t_info_table PIPELINED IS
    l_table t_id_table;
    BEGIN
      l_table := p;
    END;

  FUNCTION get_cursor RETURN t_info_cur IS
    l_table  t_id_table;
    l_result t_info_cur;
    BEGIN

      OPEN l_result FOR SELECT * FROM TABLE (buggy_report.pipe_table(l_table));

      RETURN l_result;
    END;
END;
/

DECLARE
  l_cur buggy_report.t_info_cur;
  l_rec l_cur%ROWTYPE;
  PROCEDURE hello IS BEGIN NULL; END;
BEGIN

  l_cur := buggy_report.get_cursor();

  -- hello;

  LOOP
    FETCH l_cur INTO l_rec;
    EXIT WHEN l_cur%NOTFOUND;
  END LOOP;

  CLOSE l_cur;

  dbms_output.put_line('success');
END;
/

추가 실험을 통해 우리는 문제가 가정했던 것보다 훨씬 더 깊다는 것을 발견했습니다.

예: 패키지에 사용된 다양한 요소buggy_report우리는 얻을 수 있습니다.ORA-03113: end-of-file on communication channel스크립트를 실행할 때(질문에서).의 유형을 변경하여 수행할 수 있습니다.t_id_table로.VARRAY또는TABLE .. INDEX BY ..이 게시물의 주제에서 벗어난 다양한 예외로 이어지는 많은 방법과 변형이 있습니다.

한 가지 더 흥미로운 것은 편집 시간이buggy_report패키지 사양은 최대 25초가 소요될 수 있으며, 일반적으로 약 0.05초가 소요됩니다.그것은 분명히 존재 여부에 달려 있다고 말할 수 있습니다.TYPE t_id_table의 매개 변수pipe_table함수 선언 및 "긴 시간 컴파일"은 설치 사례의 40%에서 발생합니다.그래서 문제가 있는 것 같습니다.local collection types in SQL컴파일 중에 간헐적으로 나타납니다.

Oracle 12.1.0.2는 SQL에서 로컬 수집 유형을 사용하는 데 버그가 있음을 알 수 있습니다.

얻을 수 있는 최소한의 예ORA-22163그리고.ORA-03113다음과 같습니다.거기서 우리는 똑같이 가정합니다.buggy_report질문과 같이 포장합니다.

-- produces 'ORA-03113: end-of-file on communication channel'
DECLARE   
  l_cur buggy_report.t_info_cur;

  FUNCTION get_it RETURN buggy_report.t_info_cur IS BEGIN RETURN buggy_report.get_cursor(); END;    
BEGIN
   l_cur := get_it();

   dbms_output.put_line('');
END;
/

-- produces 'ORA-22163: left hand and right hand side collections are not of same type'
DECLARE  
  l_cur buggy_report.t_info_cur;

  PROCEDURE hello IS BEGIN NULL; END;
BEGIN
  l_cur := buggy_report.get_cursor;

  -- comment `hello` and exception disappears
  hello;

  CLOSE l_cur;
END;
/

예, Oracle 12c에서는 SQL의 로컬 수집 유형을 사용할 수 있습니다.

Documentation Database기능 가이드에는 다음과 같은 내용이 있습니다.

PL/SQL-to-SQL 인터페이스에서 허용되는 PL/SQL 관련 데이터 유형

테이블 연산자는 이제 PL/SQL에서 데이터 유형이 선언된 컬렉션의 PL/SQL 프로그램에서 사용할 수 있습니다.이를 통해 데이터 유형을 PL/SQL 연관 배열로 지정할 수도 있습니다. 이전 릴리스에서는 컬렉션의 데이터 유형을 스키마 수준에서 선언해야 했습니다.

하지만, 왜 당신의 코드가 작동하지 않는지 모르겠습니다, 아마도 이 새로운 기능은 여전히 버그가 있을 것입니다.

저는 당신의 예를 만지작거렸습니다.Oracle 12c가 SQL 문에서 PL/SQL 컬렉션을 사용할 수 있는 비결은 Oracle이 호환되는 SQL 유형 특성을 가진 대리 스키마 개체 유형을 생성하고 쿼리에서 이러한 대리 유형을 사용한다는 것입니다.당신의 케이스는 벌레처럼 보입니다.실행을 추적했는데, 존재하지 않는 경우 한 번만 생성됩니다.따라서 파이프라인 함수를 실행하는 동안 유효 유형이 변경되거나 재컴파일되지 않습니다(ALTER 문을 사용하여 암시적 재컴파일이 수행되는지 여부를 알 수 없음).그리고 이 문제는 다음을 사용하는 경우에만 발생합니다.p 변수는 의매변수에 있습니다.pipe_table기능.전화하지 않으면l_table := p;활성화된 메서드 호출에서도 코드가 성공적으로 실행됩니다.

언급URL : https://stackoverflow.com/questions/33163016/does-oracle-12-have-problems-with-local-collection-types-in-sql

반응형