Oracle
 sql >> база данни >  >> RDS >> Oracle

ORA-22905 - при запитване на тип таблица с оператор select

Възможно е да се заявяват типове таблици в PL/SQL, но само вложени таблици и променливи, чиито типове са декларирани на ниво схема, т.е. извън PL/SQL.

Грешката

ORA-22905:няма достъп до редове от невложен елемент в таблица

означава, че се опитвате да правите заявка от неподдържан тип таблица. Вашият тип type_tab_AB е асоциативен масив, поради INDEX BY BINARY_INTEGER клауза. Премахнете INDEX BY BINARY_INTEGER клауза, за да направите своя type_tab_AB тип вложена таблица. (Променливите също биха работили тук, но не бих препоръчал да ги използвате, освен ако не знаете горна граница за броя на редовете, които да очаквате. Когато декларирате тип променлива, трябва да посочите максималния брой елементи, докато типовете вложени таблици имат няма такова ограничение.)

След като направите тази промяна, вашият код все още може да не работи. Следващата грешка, която може да получите (вижте бележката в долната част, ако не го направите), е

PLS-00642:типове локални колекции не са разрешени в SQL изрази

Това е така, защото типът, който избирате, е деклариран в PL/SQL. Трябва да декларирате type_tab_AB и record_AB извън PL/SQL, като използвате CREATE TYPE ... .

Следващият проблем, който ще срещнете, ще бъде поради ключовата дума RECORD . Типовете записи могат да се създават само в PL/SQL, не могат да се създават на ниво схема. Променете RECORD към OBJECT за да поправите това.

Последният проблем, който ще срещнете, е с SELECT t.AA, t.BB BULK COLLECT INTO tab_AB FROM ... изявление. В този вид тази заявка ще ви даде следната грешка:

PL/SQL:ORA-00947:няма достатъчно стойности

Избирате два елемента от всеки ред и предоставяте само една таблица за групово вмъкване на данните. Oracle не може да разбере, че искате да поставите двата елемента във вашия record_AB Тип. Можете да коригирате това сравнително лесно, като промените заявката на 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_AB в курсор и използва променлива на курсора SQL*Plus за изброяване на съдържанието му. Резултатът, който получавам, когато стартирам скрипта на Oracle 11g XE, след всички съобщения 'Type created' и 'PL/SQL procedure successfully completed', е както следва:

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

ЗАБЕЛЕЖКА: За простота предположих, че питащият използва Oracle 11 или по-стара версия. В Oracle 12 вярвам, че ви е позволено да използвате типове, декларирани в PL/SQL в SQL заявка, така че може да не срещнете грешката PLS-00642. Не мога да кажа какви други промени в моя отговор може да са необходими и за Oracle 12, тъй като все още не съм използвал Oracle 12.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Изчислете разликата между 2 дата/часа в Oracle SQL

  2. Грешка при отпечатване на променлива REFCURSOR като OUT параметър в процедурата в Oracle 11g

  3. Вземете ДЪЛЖИНАТА на LONG RAW

  4. Oracle.DataAccess.dll не може да бъде намерен, въпреки че съществува

  5. Oracle Dynamic Pivoting