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;
/
Это дает вам поиск по значению символьного ключа и позволяет делать все оптом.