PL/ SQL: выбор из таблицы в массив assoc

Я пытаюсь выбрать данные в ассоциативный массив 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 ответов


просто прочитайте свой комментарий к ответу 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;

было бы аккуратно, если бы это было возможно, но это не простой способ достичь этого.

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

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

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 edition, вы должны рассмотреть следствием установлено кэширование вместо.


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

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

например

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

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