Oracle
 sql >> Baza danych >  >> RDS >> Oracle

ORA-22905 - podczas zapytania o typ tabeli za pomocą instrukcji SELECT

Możliwe jest odpytywanie typów tabel w PL/SQL, ale tylko tabele zagnieżdżone i zmienne, których typy są zadeklarowane na poziomie schematu, tj. poza PL/SQL.

Błąd

ORA-22905:brak dostępu do wierszy z niezagnieżdżonego elementu tabeli

oznacza, że ​​próbujesz wykonać zapytanie z nieobsługiwanego typu tabeli. Twój typ type_tab_AB jest tablicą asocjacyjną, ponieważ INDEX BY BINARY_INTEGER klauzula. Usuń INDEX BY BINARY_INTEGER klauzula, aby utworzyć type_tab_AB zagnieżdżony typ tabeli. (Varrays również by tu działały, ale nie zalecałbym ich używania, chyba że znasz górną granicę liczby oczekiwanych wierszy. Deklarując typ varray, musisz określić maksymalną liczbę elementów, podczas gdy typy tabel zagnieżdżonych mają nie ma takiego ograniczenia.)

Po wprowadzeniu tej zmiany Twój kod może nadal nie działać. Następny błąd, który możesz otrzymać (patrz uwaga na dole, jeśli nie) to

PLS-00642:lokalne typy kolekcji nie są dozwolone w instrukcjach SQL

Dzieje się tak, ponieważ typ, który wybierasz, jest zadeklarowany w PL/SQL. Musisz zadeklarować type_tab_AB i record_AB poza PL/SQL, używając CREATE TYPE ... .

Następny problem, który napotkasz, będzie spowodowany słowem kluczowym RECORD . Typy rekordów można tworzyć tylko w PL/SQL, nie można ich tworzyć na poziomie schematu. Zmień RECORD do OBJECT by to naprawić.

Ostatni problem, jaki napotkasz, dotyczy SELECT t.AA, t.BB BULK COLLECT INTO tab_AB FROM ... oświadczenie. W obecnej postaci to zapytanie spowoduje następujący błąd:

PL/SQL:ORA-00947:za mało wartości

Wybierasz dwa elementy z każdego wiersza i udostępniasz tylko jedną tabelę do zbiorczego wstawiania danych. Oracle nie może do końca zrozumieć, że chcesz umieścić te dwa elementy w swoim record_AB rodzaj. Możesz to dość łatwo naprawić, zmieniając zapytanie na SELECT record_AB(t.AA, t.BB) BULK COLLECT INTO tab_AB FROM ... .

Łącznie te zmiany powinny rozwiązać problem. Oto pełny skrypt SQL*Plus, który tworzy tabelę testową z niektórymi danymi testowymi i sprawdza, czy może wykonać zapytanie o typ tabeli:

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

Wstawiłem wynik SELECT zawartość tab_AB do kursora i użył zmiennej kursora SQL*Plus, aby wyświetlić jego zawartość. Dane wyjściowe, które otrzymuję po uruchomieniu skryptu w Oracle 11g XE, po wszystkich komunikatach „Typ utworzony” i „Procedura PL/SQL pomyślnie zakończona”, są następujące:

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

UWAGA: Dla uproszczenia założyłem, że pytający używa Oracle 11 lub starszego. Uważam, że w Oracle 12 możesz używać typów zadeklarowanych w PL/SQL w zapytaniu SQL, więc możesz nie napotkać błędu PLS-00642. Nie mogę powiedzieć, jakie inne zmiany w mojej odpowiedzi mogą być również konieczne dla Oracle 12, ponieważ jeszcze nie korzystam z 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. Jak zaktualizować za pomocą wewnętrznego sprzężenia w Oracle

  2. oratop

  3. 4 sposoby znajdowania wierszy zawierających wielkie litery w Oracle

  4. Przyznanie praw do procedury składowanej innemu użytkownikowi Oracle

  5. ORA-01461:może powiązać wartość LONG tylko w celu wstawienia do kolumny LONG — występuje podczas wykonywania zapytania