web-dev-qa-db-fra.com

PL/SQL: Sélection d'une table dans un tableau assoc

J'essaie de sélectionner des données dans un tableau associatif pl/sql en une requête. Je sais que je peux le faire avec une clé codée en dur, mais je voulais voir s'il était possible de référencer une autre colonne (la colonne clé).


DECLARE
TYPE VarAssoc IS TABLE OF varchar2(2) INDEX BY varchar2(3);
vars VarAssoc;
BEGIN
SELECT foo, bar INTO vars(foo) FROM schema.table;
END;

Je reçois une erreur en disant que foo doit être déclaré quand je fais cela. Existe-t-il un moyen de créer mon tableau associé en une seule requête ou dois-je avoir recours à une boucle FOR?

13
Seaux

Lisez simplement votre commentaire sur la réponse d’APC, il semble que vous l’ayez compris par vous-même. Mais je me suis dit que je mettrais la réponse de toute façon pour les futurs chercheurs.

Ce code est plus simple, mais n’a pas l’avantage d’avoir l’utilisation de BULK COLLECT. Parcourez simplement les lignes renvoyées par la requête et définissez les éléments du tableau associatif individuellement.

DECLARE
  TYPE VarAssoc IS TABLE OF varchar2(200) INDEX BY varchar2(30);
  vars VarAssoc;
BEGIN
  FOR r IN (SELECT table_name,tablespace_name FROM user_tables) LOOP
    vars(r.table_name) := r.tablespace_name;
  END LOOP;

  dbms_output.put_line( vars('Java$OPTIONS') );
END;
16
Dave Costa

Ce serait bien si cela était possible, mais ce n’est pas une façon simple d’y parvenir.

Ce que nous pouvons faire, c'est charger les données dans une collection PL/SQL normale, puis dans un tableau associatif. Cela est plus rapide que de simplement tourner autour de la table est une question de principe: cela n'a probablement pas d'importance, sauf si nous avons affaire à des charges de données.

Compte tenu de ces données de test ...

SQL> select * from t23
  2  order by c1
  3  /

C1 C2
-- ---
AA ABC
BB BED
CC CAR
DD DYE
EE EYE
ZZ Zoo

6 rows selected.

SQL>

... nous pouvons peupler un tableau associatif en deux étapes:

SQL> set serveroutput on
SQL>
SQL> declare
  2      type varassoc is table of varchar2(3) index by varchar2(2);
  3      vars varassoc;
  4
  5      type nt is table of t23%rowtype;
  6      loc_nt nt;
  7
  8  begin
  9      select * bulk collect into loc_nt from t23;
 10      dbms_output.put_line('no of recs = '||sql%rowcount);
 11
 12      for i in loc_nt.first()..loc_nt.last()
 13      loop
 14          vars(loc_nt(i).c1) := loc_nt(i).c2;
 15      end loop;
 16
 17      dbms_output.put_line('no of vars = '||vars.count());
 18
 19      dbms_output.put_line('ZZ = '||vars('ZZ'));
 20
 21  end;
 22  /
no of recs = 6
no of vars = 6
ZZ = Zoo

PL/SQL procedure successfully completed.

SQL>

La vraie question est probablement de savoir si le remplissage d'un tableau associatif est plus efficace que la simple sélection de lignes dans la table. Certainement, si vous avez l'édition Enterprise 11g, vous devriez plutôt envisager/ la mise en cache des résultats

6
APC

êtes-vous absolument marié à des tableaux associatifs? Et je suppose que vous le faites parce que vous souhaitez pouvoir effectuer une recherche dans le tableau à l'aide d'une clé de caractère.

Si tel est le cas, avez-vous envisagé de l'implémenter comme un type de collection?

par exemple.

CREATE OR REPLACE TYPE VAR_ASSOC as OBJECT(
  KEYID   VARCHAR2(3),
  DATAVAL VARCHAR2(2)
)
/

CREATE OR REPLACE TYPE VAR_ASSOC_TBL AS TABLE OF VAR_ASSOC
/

CREATE OR REPLACE PROCEDURE USE_VAR_ASSOC_TBL
AS
  vars Var_Assoc_tbl; 
  -- other variables...
BEGIN 
    select cast ( multiset (
                        select foo as keyid,
                               bar as dataval
                        from   schema.table
                           ) as var_Assoc_tbl
                )
     into vars
     from dual;   
     -- and later, when you want to do your lookups
     select  ot.newfoo 
            ,myvars.dataval
            ,ot.otherval
     into   ....       
     from   schema.other_Table ot
     join   table(vars) as myvars
     on     ot.newfoo = myvars.keyid;
end;
/     

Cela vous donne la valeur de clé de recherche par caractère et vous permet de tout faire en bloc.

0