Объявление и заполнение индекса ассоциативного массива
При написании программы появилась необходимость в создании ассоциативного массива с использованием индекса, в связи с этим есть несколько вопросов:
Правильно понимаю, что при объявлении индекса тип данных может быть только varchar2, BINARY_INTEGER, PLS_INTEGER, никаких integer и number?
Допустим, я объявил для массива индекс index by SALE_TRANS.Player_Info%type, затем в теле программы я заполняю массив данными:
select
Player_Info(varchar2),
id (number),
trns(integer),
email(varchar2) bulk collect into happy
from SALE_TRANS t
where t.Trns_ID = 2497170`
Индекс автоматически создастся по столбцу Player_Info?
Если я объявляю индекс index by VARCHAR2(3333), то при заполнении массива:
select
Player_Info(varchar2),
id (number),
trns(integer),
email(varchar2) bulk collect into happy
from SALE_TRANS t
where t.Trns_ID = 2497170
То индекс создастся на каком столбце?
Ответы (2 шт):
- Да, верно.
2,3. Bulk Collect не работает с ассоциативными массивами, кроме индексированых pls_integer. Если pls_integer, то вам надо указывать отдельные поля:
SELECT employee_id, last_name
BULK COLLECT INTO enums, names
FROM employees
Посмотрим, что говорит об ассоциативных коллекциях оф.источники (выделил жирным то, что надо обязательно понять и усвоить):
An associative array (formerly called PL/SQL table or index-by table) is a set of key-value pairs. Each key is a unique index, used to locate the associated value with the syntax
variable_name(index).The data type of index can be either a string type (VARCHAR2, VARCHAR, STRING, or LONG) or PLS_INTEGER. Indexes are stored in sort order, not creation order.
То есть, лучше представить, что ассоциативные коллекции это упорядоченный по уникальному ключу набор значений, чем индексированный набор значений.
В SQL запросах могут использоваться только ассоциативные коллекции с типом ключа - PLS_INTEGER. При этом, текущему ключу будет присвоено значение не какого-либо столбца, а именно порядковый номер записи в результирующем наборе (result set). То ест, это всегда и без исключений последовательность без пропусков - 1..N (отсюда и устаревшее название - index by table).
Исходя из выше изложенного, если предполагаеется использовать ассоциативные коллекции, как показанно в вопросе, то лучше сразу обратится к вложенным таблицам.
В заключениe, несколько воспроизводимых примеров (на db<>fiddle). Подготовка схемы:
create table t (id, memo, created) as
select rownum, 'memo '||lpad (rownum, 4, '0'), sysdate
from dual connect by level<=3;
/
create or replace package pack as
type rec is record (id int, memo varchar2 (96), created date default sysdate);
type arrbynum is table of t%rowtype index by pls_integer;
type arrbykey is table of t%rowtype index by varchar2 (32);
end;
/
В SQL запросах не могут быть использованы ассоциативные коллекции с символьным типом ключа:
declare k pack.arrbykey;
begin
select * bulk collect into k from t;
end;
/
PLS-00657: Implementation restriction: bulk SQL with associative arrays with VARCHAR2 key is not supported.
Функционал в #1 и #2 полностью эквивалентен, #2 поясняет, что делает "под капотом" #1:
declare
n pack.arrbynum;
rc sys_refcursor;
rec t%rowtype;
begin
--#1
select * bulk collect into n from t;
--#2
open rc for select * from t;
loop fetch rc into rec;
exit when rc%notfound;
n(rc%rowcount) := rec;
end loop;
end;
/
Инициализацию ассоциативной коллекции данными из SQL запроса можно выполнить так:
declare
k pack.arrbykey;
key char (8);
begin
for r in (select * from t) loop
key := 'code'||lpad (r.id, 4, '0');
k (key) := r;
end loop;
end;
/