Getting index of element in PL/SQL collection Getting index of element in PL/SQL collection oracle oracle

Getting index of element in PL/SQL collection


Not sure, if this really helps, or if you think it is more elegant:

create type t_test as table of varchar2(1);/DECLARE--TYPE t_test IS TABLE OF VARCHAR2(1);  v_test t_test;  function get_index(q in t_test, c in varchar2) return number is    ind number;  begin    select min(rn) into ind from (      select column_value cv, rownum rn       from table(q)     )    where cv = c;    return ind;  end get_index;BEGIN  v_test := NEW t_test('A', 'B', 'A');  dbms_output.put_line( 'A: ' || get_index( v_test, 'A' ) );  dbms_output.put_line( 'B: ' || get_index( v_test, 'B' ) );  dbms_output.put_line( 'C: ' || get_index( v_test, 'C' ) );END;/show errorsdrop type t_test;


I don't think there is a built-in function that searches a collection. However, if you know you will need to search a collection a lot, you could build an index. Adding element to the collection will be a bit more expensive, but looking for an element will be an O(1) operation (instead of O(n) for a brute force search). For example, you could use something like this:

SQL> DECLARE  2     TYPE t_test IS TABLE OF VARCHAR2(1);  3     TYPE t_test_r IS TABLE OF NUMBER INDEX BY VARCHAR2(1);  4    5     v_test t_test;  6     v_test_r t_test_r;  7    8     FUNCTION get_index(p_test_r t_test_r,  9                        p_element VARCHAR2) RETURN NUMBER IS 10     BEGIN 11        RETURN p_test_r(p_element); 12     EXCEPTION 13        WHEN no_data_found THEN 14           RETURN NULL; 15     END get_index; 16   17     PROCEDURE add_element(p_test IN OUT t_test, 18                           p_test_r IN OUT t_test_r, 19                           p_element VARCHAR2) IS 20     BEGIN 21        p_test.extend; 22        p_test(p_test.count) := p_element; 23        p_test_r(p_element) := least(p_test.count, 24                                     nvl(get_index(p_test_r, p_element), 25                                         p_test.count)); 26     END add_element; 27  BEGIN 28     v_test := NEW t_test(); 29     add_element(v_test, v_test_r, 'A'); 30     add_element(v_test, v_test_r, 'B'); 31     add_element(v_test, v_test_r, 'A'); 32     dbms_output.put_line('A: ' || get_index(v_test_r, 'A')); 33     dbms_output.put_line('B: ' || get_index(v_test_r, 'B')); 34     dbms_output.put_line('C: ' || get_index(v_test_r, 'C')); 35  END; 36  /A: 1B: 2C: PL/SQL procedure successfully completed

You could also define a record that contains both arrays and all functions/procedures to interact with arrays would use this record type.


When in doubt, consult the documentation ;) (here)

DECLARE  TYPE aa_type_int IS TABLE OF INTEGER INDEX BY PLS_INTEGER;  aa_int  aa_type_int;  PROCEDURE print_first_and_last IS  BEGIN    DBMS_OUTPUT.PUT_LINE('FIRST = ' || aa_int.FIRST);    DBMS_OUTPUT.PUT_LINE('LAST = ' || aa_int.LAST);  END print_first_and_last;BEGIN  aa_int(1) := 3;  aa_int(2) := 6;  aa_int(3) := 9;  aa_int(4) := 12;  DBMS_OUTPUT.PUT_LINE('Before deletions:');  print_first_and_last;  aa_int.DELETE(1);  aa_int.DELETE(4);  DBMS_OUTPUT.PUT_LINE('After deletions:');  print_first_and_last;END;/

Result:

Before deletions:FIRST = 1LAST = 4After deletions:FIRST = 2LAST = 3