Oracle
 sql >> Base de données >  >> RDS >> Oracle

ORA-22905 - lors de l'interrogation d'un type de table avec une instruction select

Il est possible d'interroger les types de tables en PL/SQL, mais uniquement les tables imbriquées et les varrays dont les types sont déclarés au niveau du schéma, c'est-à-dire en dehors de PL/SQL.

L'erreur

ORA-22905 :impossible d'accéder aux lignes d'un élément de tableau non imbriqué

signifie que vous essayez d'interroger à partir d'un type de table non pris en charge. Votre type type_tab_AB est un tableau associatif, à cause du INDEX BY BINARY_INTEGER clause. Supprimez le INDEX BY BINARY_INTEGER clause pour rendre votre type_tab_AB un type de tableau imbriqué. (Les varrays fonctionneraient également ici, mais je ne recommanderais pas de les utiliser à moins que vous ne connaissiez une limite supérieure pour le nombre de lignes à attendre. Lors de la déclaration d'un type varray, vous devez spécifier le nombre maximum d'éléments, alors que les types de table imbriqués ont aucune restriction de ce type.)

Après avoir effectué cette modification, votre code peut toujours ne pas fonctionner. La prochaine erreur que vous pouvez obtenir (voir la note en bas si vous ne le faites pas) est

PLS-00642 :types de collections locales non autorisés dans les instructions SQL

En effet, le type que vous sélectionnez est déclaré dans PL/SQL. Vous devez déclarer type_tab_AB , et record_AB en dehors de PL/SQL, en utilisant CREATE TYPE ... .

Le prochain problème que vous rencontrerez sera à cause du mot-clé RECORD . Les types d'enregistrement ne peuvent être créés qu'à l'intérieur de PL/SQL, ils ne peuvent pas être créés au niveau du schéma. Modifier RECORD à OBJECT pour résoudre ce problème.

Le dernier problème que vous rencontrerez est avec le SELECT t.AA, t.BB BULK COLLECT INTO tab_AB FROM ... déclaration. Dans l'état actuel des choses, cette requête vous donnera l'erreur suivante :

PL/SQL :ORA-00947 :pas assez de valeurs

Vous sélectionnez deux éléments dans chaque ligne et ne fournissez qu'un seul tableau dans lequel insérer les données en masse. Oracle n'arrive pas à comprendre que vous voulez insérer les deux éléments dans votre record_AB taper. Vous pouvez résoudre ce problème assez facilement en modifiant la requête en SELECT record_AB(t.AA, t.BB) BULK COLLECT INTO tab_AB FROM ... .

Collectivement, ces changements devraient résoudre le problème. Voici un script SQL*Plus complet qui crée une table de test avec des données de test et vérifie qu'il peut interroger le type de table :

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

J'ai mis le résultat de SELECT ing le contenu de tab_AB dans un curseur et utilisé une variable de curseur SQL*Plus pour lister son contenu. La sortie que j'obtiens lorsque j'exécute le script sur Oracle 11g XE, après tous les messages "Type créé" et "Procédure PL/SQL terminée avec succès", est la suivante :

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

REMARQUE : Pour plus de simplicité, j'ai supposé que le questionneur utilise Oracle 11 ou une version antérieure. Dans Oracle 12, je pense que vous êtes autorisé à utiliser des types déclarés en PL/SQL dans une requête SQL, vous ne rencontrerez donc peut-être pas l'erreur PLS-00642. Je ne peux pas dire quelles autres modifications de ma réponse pourraient également être nécessaires pour Oracle 12 car je n'ai pas encore utilisé Oracle 12.