programing

ORA-22905 - Select 문을 사용하여 테이블 유형을 쿼리할 수 있습니다.

abcjava 2023. 6. 25. 18:11
반응형

ORA-22905 - Select 문을 사용하여 테이블 유형을 쿼리할 수 있습니다.

 DECLARE
 TYPE record_AB IS RECORD
   (
      AA              VARCHAR2 (16 BYTE),
      BB    VARCHAR2 (16 BYTE)
   );

  TYPE type_tab_AB IS TABLE OF record_AB
                        INDEX BY BINARY_INTEGER;

  tab_AB   type_tab_AB;

  BEGIN
   SELECT *
    BULK COLLECT INTO tab_AB FROM...
    ..
    SELECT * FROM TABLE (tab_AB) ;

SELECT from TABLE 문에 도달하면 "ORA-22905: non-nested table item에서 행에 액세스할 수 없음"이 표시됩니다.

PLSQL 내에서 테이블 유형을 쿼리하는 것이 가능합니까?

PL/SQL에서 테이블 형식을 쿼리할 수 있지만, PL/SQL 외부와 같은 스키마 수준에서 유형이 선언된 중첩된 테이블 및 배열만 쿼리할 수 있습니다.

오류

ORA-22905: 중첩되지 않은 테이블 항목의 행에 액세스할 수 없습니다.

지원되지 않는 테이블 유형에서 쿼리를 시도하고 있음을 의미합니다.당신의 타입type_tab_AB연상배열, 그 이유는INDEX BY BINARY_INTEGER제거합니다.INDEX BY BINARY_INTEGER당신을 만들기 위한 조항type_tab_AB중첩된 테이블 유형입니다. (Varray도 여기서 사용할 수 있지만, 예상되는 행 수에 대한 상한을 알고 있지 않으면 사용하지 않는 것이 좋습니다.배열 유형을 선언할 때는 최대 요소 수를 지정해야 하지만 중첩된 테이블 유형에는 이러한 제한이 없습니다.

변경한 후에도 코드가 작동하지 않을 수 있습니다.다음으로 발생할 수 있는 오류는 다음과 같습니다(그렇지 않은 경우 아래 참고 참조).

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

이는 선택하려는 유형이 PL/SQL 내에서 선언되기 때문입니다.선언해야 합니다.type_tab_AB,그리고.record_ABPL/SQL 외부, 사용CREATE TYPE ....

다음에 발생하는 문제는 키워드 때문일 것입니다.RECORD레코드 유형은 PL/SQL 내에서만 만들 수 있으며 스키마 수준에서는 만들없습니다.바꾸다RECORD로.OBJECT이 문제를 해결하기 위해.

마지막으로 발생하는 문제는 다음과 같습니다.SELECT t.AA, t.BB BULK COLLECT INTO tab_AB FROM ...진술.현재 상태에서 이 쿼리는 다음과 같은 오류를 제공합니다.

PL/SQL: ORA-00947: 값이 부족합니다.

각 행에서 두 개의 항목을 선택하고 데이터를 대량으로 삽입할 테이블을 하나만 제공합니다.오라클은 당신이 두 항목을 당신의 웹사이트에 넣길 원하는지 잘 알지 못합니다.record_ABtype. 쿼리를 로 변경하면 이 문제를 상당히 쉽게 해결할 수 있습니다.SELECT record_AB(t.AA, t.BB) BULK COLLECT INTO tab_AB FROM ....

전체적으로 이러한 변경 사항이 문제를 해결해야 합니다.다음은 일부 테스트 데이터로 테스트 테이블을 만들고 테이블 유형을 쿼리할 수 있는지 확인하는 전체 SQL*Plus 스크립트입니다.

CREATE TABLE some_table (AA VARCHAR2(16 BYTE), BB VARCHAR2(16 BYTE));

INSERT INTO some_table (AA, BB) VALUES ('aa 1', 'bb 1');
INSERT INTO some_table (AA, BB) VALUES ('aaaaaaaaaa 2', 'b 2');
INSERT INTO some_table (AA, BB) VALUES ('aaaaa 3', 'bbbbbbbbbbbbbb 3');
COMMIT;

VARIABLE curs REFCURSOR;

CREATE OR REPLACE TYPE record_AB AS OBJECT
   (
      AA    VARCHAR2 (16 BYTE),
      BB    VARCHAR2 (16 BYTE)
   );
/

CREATE OR REPLACE TYPE type_tab_AB IS TABLE OF record_AB;
/

DECLARE
  tab_AB   type_tab_AB;
BEGIN
  SELECT record_AB(t.AA, t.BB)
    BULK COLLECT INTO tab_AB 
    FROM some_table t;

  OPEN :curs FOR SELECT * FROM TABLE (tab_AB) ;
END;
/

PRINT :curs

의 결과를 기록했습니다.SELECT의 내용을 입력합니다.tab_ABSQL*Plus 커서 변수를 사용하여 내용을 나열했습니다.'Type created' 및 'PL/SQL procedure successfully completed' 메시지가 모두 표시된 후 Oracle 11g XE에서 스크립트를 실행할 때 표시되는 출력은 다음과 같습니다.

AA               BB
---------------- ----------------
aa 1             bb 1
aaaaaaaaaa 2     b 2
aaaaa 3          bbbbbbbbbbbbbb 3

참고: 간단히 설명하기 위해 질문자가 Oracle 11 이상을 사용하고 있다고 가정합니다.Oracle 12에서는 SQL 쿼리에서 PL/SQL로 선언된 유형을 사용할 수 있으므로 PLS-00642 오류가 발생하지 않을 수 있습니다.아직 Oracle 12를 사용하지 않았기 때문에 Oracle 12에 대해 어떤 다른 변경 사항이 필요할지 모르겠습니다.

pl/sql 블록 내에 생성된 형식은 쿼리할 수 없습니다.sql 프롬프트에서 생성한 다음 쿼리할 수 있습니다.아래 예제 참조:

scott@ORA92> CREATE OR REPLACE TYPE emp_type AS OBJECT
  2    (id   NUMBER,
  3     name VARCHAR2(20));
  4  /

Type created.

scott@ORA92> CREATE OR REPLACE TYPE emp_tab AS TABLE OF emp_type;
  2  /

Type created.

scott@ORA92> VARIABLE g_ref REFCURSOR
scott@ORA92> DECLARE
  2    employees emp_tab := emp_tab();
  3  BEGIN
  4    employees.EXTEND(2);
  5    employees(1) := emp_type (1, 'name1');
  6    employees(2) := emp_type (2, 'name2');
  7    OPEN :g_ref FOR
  8    SELECT * FROM TABLE (CAST (employees AS emp_tab));
  9  END;
 10  /

언급URL : https://stackoverflow.com/questions/19208264/ora-22905-when-querying-a-table-type-with-a-select-statement

반응형