Not quite sure what you mean by 'return rows', but to loop over them in 'index' order you can loop from 1 to count:
declare
arr Varchar2ArrayType := Varchar2ArrayType() ;
begin
arr.extend(3) ;
arr(1) := 'ZXC' ;
arr(2) := 'ASD' ;
arr(3) := 'GHJ' ;
for i in 1..arr.count loop
dbms_output.put_line(arr(i)) ;
end loop ;
end ;
/
ZXC
ASD
GHJ
PL/SQL procedure successfully completed.
You could also use for i in arr.first..arr.last loop here; docs for first and last are here. If you're manipulating (i.e. deleting from) the collection after populating it then you need to be aware of how those functions behave, as the documentation illustrates.
You can't order using the select from table syntax because arr is only in-scope within the table() function; it is not visible to the order by clause and the index value used within the nested table doesn't exist. If you just leave off the order by clause then the rows seem to be ordered by the index anyway, but I don't think that's guaranteed.
...
for rec in (select rownum as rn, column_value from table(arr)) loop
dbms_output.put_line(rec.rn ||':'|| rec.column_value) ;
end loop ;
...
1:ZXC
2:ASD
3:GHJ
You could perhaps use a pipelined table function to return a record type that includes both the index and value as two columns if that isn't robust enough.