[ DarkMan @ 25.09.2012. 14:15 ] @
Da li je moguce za indeks kolekcije koristiti vrednost polja iz unutrasnjeg upita?
Sledeca skripta nece da se izvrsi:
Code:

declare
  type ime_record is record (ime varchar2(50), pol varchar2(1));
  type ime_type is table of ime_record index by pls_integer;
  v_imena ime_type;
  v_imena_max integer;
  v_ref sys_refcursor;
  v_out ime_type;  
begin
  
  v_imena(1).ime := 'ALEKSA';
  v_imena(1).pol := 'M';
  v_imena(2).ime := 'ALEKSANDAR';
  v_imena(2).pol := 'M';
  v_imena(3).ime := 'ALEKSANDRA';
  v_imena(3).pol := 'Z';
  v_imena(4).ime := 'ANA';
  v_imena(4).pol := 'Z';
  v_imena(5).ime := 'ANASTASIJA';
  v_imena(5).pol := 'Z';
  
  v_imena_max := v_imena.count;
  
    
  select v_imena(index_ime).ime, v_imena(index_ime).pol
  bulk collect into v_out               
  from (select trunc(dbms_random.value(1, v_imena_max)) as index_ime
        from (select rownum as rnum from all_objects where rownum <= 1000));

end;

vraca gresku:
Code:

ORA-06550: line 24, column 42:
PLS-00201: identifier 'INDEX_IME' must be declared
[ darkosos @ 26.09.2012. 08:03 ] @
Izgleda prilicno komplikovano, ali nevezano za to, stavi neko ime za zagradu koja ti predstavlja inline view iz koga selektujes, npr.
select x.polje from (select polje from ... ) x;
[ DarkMan @ 26.09.2012. 11:23 ] @
Postavio sam isto pitanje na Oracle forumu
https://forums.oracle.com/forums/message.jspa?messageID=10597463

Izgleda da nije moguce to sto sam hteo.
[ djoka_l @ 26.09.2012. 11:59 ] @
Prvo, ovo može bolje:
Code:

select trunc(dbms_random.value(1, v_imena_max)) as index_ime
        from (select rownum as rnum from all_objects where rownum <= 1000)

Nepotrebna komplikacija, trebalo je da napišeš ovako nešto:
Code:

select trunc(dbms_random.value(1, v_imena_max)) as index_ime from all_objects where rownum <= 1000

Drugo, dbms_random.value(1, v_imena_max) ti daje brojeve od 1 do v_imena_max-1 . Trebalo je da napišeš v_imena_max := v_imena.count+1 da bi radilo kako treba.

Treće, osim što ne radi, BULK COLLECT čak i kad bi radio bio bi sporiji od FOR petlje jer se obraća bazi (čita all_objects, formira u TMP table space rezultat upita mulja gomilu blokova itd.).

Umesto toga
Code:

for i in 1..1000 loop
   idx := dbms_random.value(1, v_imena_max);
   v_out(i).ime := v_imena(idx).ime;
   v_out(i).pol := v_imena(idx).pol;
end loop;
[ DarkMan @ 26.09.2012. 12:32 ] @
A moze i jos bolje:
Code:

select trunc(dbms_random.value(1, v_names_max)) as name_index from dual connect by rownum <= 1000


Pitanje je bilo vezano za index kolekcije a primer samo ilustruje problem.
Originalna skripta radi insert random imena i prezimena.
Odradio sam skriptu sa loop-om i onda sam pokusao da isto to odradim jednim kompleksnijim upitom sa nadom da se malo ubrza procedura.

Na oracle forumu su mi odgovori da ne moze to sto sam hteo tako da cu se zadrzati na loop-u.
Inace na oracle forumu sam takodje postavio pitanje zasto sledece ne radi kako treba:

Code:

declare
  type list_item is table of integer index by pls_integer;
  v_list list_item;
begin
 
  v_list(1) := 10;
  v_list(2) := 9;
  v_list(3) := 8;
  v_list(4) := 7;
  v_list(5) := 6;
  v_list(6) := 5;
  v_list(7) := 4;
  v_list(8) := 3;
  v_list(9) := 2;
  v_list(10) := 1;
  
  for rec in (select (1 + rownum) as rnum, v_list(1 + rownum) as item from dual connect by rownum <= 9)
  loop
    dbms_output.put_line('rnum: ' || rec.rnum ||
                           ', item: ' || rec.item );
  end loop;
 
end;


Prethodna skripta daje sledeci rezultat:
Code:

rnum: 2, item: 10
rnum: 3, item: 10
rnum: 4, item: 10
rnum: 5, item: 10
rnum: 6, item: 10
rnum: 7, item: 10
rnum: 8, item: 10
rnum: 9, item: 10
rnum: 10, item: 10


Kada se rownum koristi kao index kolekcije njegova vrednost je uvek 0.
[ darkosos @ 26.09.2012. 14:25 ] @
Uradio sam neke probe i izgleda da index ne moze da bude nesto sto se nalazi u unutrasnjem upitu, bez obzira da li se koristi rownum.

Ocigledno da ovo sa rownum radi (iako lose) samo zato sto je rownum na neki nacin inicijalizovan (nulom) pre nego sto je dobio vrednost, jer inace dobija vrednost pri kraju cele price (pre eventualnog order by).

To bi zajedno sa onom prethodnom konstatacijom znacilo da index ne moze biti nepoznat u trenutku glavnog select-a.