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
'programing' 카테고리의 다른 글
MySQL에서 50K+ 레코드 가져오기에 일반 오류 발생: 1390 준비됨 문에 자리 표시자가 너무 많습니다. (0) | 2023.08.06 |
---|---|
유니코드 문자를 CSS 콘텐츠 값에 배치 (0) | 2023.08.06 |
jQuery를 사용하여 .prop을 변경해도 .change 이벤트가 트리거되지 않습니다. (0) | 2023.08.01 |
도커 컨테이너에 mariadb 백업 마운트 중 (0) | 2023.08.01 |
치명적 오류:발견되지 않은 오류: 스칼라를 어레이 경고로 사용할 수 없습니다. (0) | 2023.08.01 |