PL/SQL: выбор из таблицы в массив-ассоциированный элемент
Я пытаюсь выбрать данные в ассоциативный массив 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?
Ответы
Ответ 1
Просто прокомментируйте ответ 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;
Ответ 2
Это было бы аккуратно, если бы это было возможно, но это не простой способ добиться этого.
Что мы можем сделать, это загрузить данные в регулярную коллекцию 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 Edition, вы должны вместо этого рассмотреть кэширование набора результатов.
Ответ 3
Вы абсолютно женаты на ассоциативных массивах? И я предполагаю, что вы делаете это, потому что хотите иметь возможность выполнять поиск по массиву с помощью символьного ключа.
Если да, рассмотрели ли вы это внедрение как тип коллекции?
например.
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;
/
Это дает вам поиск по значению символьного ключа и позволяет делать все навалом.