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.