PL / SQL: выбор из таблицы в ассоциированный массив - PullRequest
13 голосов
/ 03 марта 2011

Я пытаюсь выделить данные в ассоциативный массив pl / sql в одном запросе.Я знаю, что могу сделать это с помощью жестко закодированного ключа, но я хотел посмотреть, есть ли способ, которым я мог бы вместо этого ссылаться на другой столбец (ключевой столбец).


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;

Я получаю сообщение об ошибке, что foo должно бытьобъявил, когда я это сделаю.Есть ли какой-нибудь способ создания моего связанного массива в одном запросе или мне нужно использовать цикл FOR?

Ответы [ 3 ]

17 голосов
/ 03 марта 2011

Просто прочитайте свой комментарий к ответу APC, похоже, вы сами это выяснили.Но я решила, что в любом случае добавлю ответ для будущих поисковиков.

Это более простой код, но он не имеет преимущества в скорости использования BULK COLLECT.Просто переберите строки, возвращаемые запросом, и установите элементы в ассоциативном массиве по отдельности.

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;
6 голосов
/ 03 марта 2011

Было бы неплохо, если бы это было возможно, но это не простой способ добиться этого.

Что мы можем сделать, это загрузить данные в обычную коллекцию PL / SQL и затем загрузить их вассоциативный массив.Если это быстрее, чем просто зацикливаться на столе, то это просто вопрос: вероятно, это не имеет значения, если мы не имеем дело с большим количеством данных.

Учитывая эти данные теста ...

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>

... мы можем заполнить ассоциативный массив в два этапа:

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>

Реальный вопрос, вероятно, состоит в том, работает ли заполнение ассоциативного массива лучше, чем просто выбор строк в таблице.Конечно, если у вас есть версия 11g Enterprise, вы должны вместо этого рассмотреть кэширование набора результатов .

0 голосов
/ 03 марта 2011

Вы абсолютно женаты на ассоциативных массивах? И я предполагаю, что вы делаете это, потому что вы хотите иметь возможность поиска в массиве с помощью символьного ключа.

Если это так, рассматривали ли вы реализацию этого как тип коллекции вместо

, например

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;
/     

Это дает вам поиск по значению ключа символа и позволяет вам делать все оптом.

...