2011-01-27 2 views
6

Existe-t-il une fonction intégrée pour déterminer le (premier) index d'un élément dans une collection PL/SQL?Obtention de l'index de l'élément dans la collection PL/SQL

Quelque chose comme

DECLARE 
    TYPE t_test IS TABLE OF VARCHAR2(1); 
    v_test t_test; 
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; 

A: 1 
B: 2 
C: 

Je peux utiliser ces tableaux, les tableaux ou emboîtées VARRAY, quel que soit nécessaire. Si le même élément existe plus d'une fois, alors l'index de la première occurrence est suffisant.


Sinon, je dois faire quelque chose comme

CREATE FUNCTION get_index (in_test IN t_test, in_value IN VARCHAR2) 
    RETURN PLS_INTEGER 
AS 
    i PLS_INTEGER; 
BEGIN 

i := in_test.FIRST; 
    WHILE(i IS NOT NULL) LOOP 
    IF(in_test(i) = in_value) THEN 
     RETURN i; 
    END IF; 

    i := in_test.NEXT(i); 
    END LOOP; 

    RETURN NULL; 

END get_index; 

Répondre

0

En cas de doute, consultez la 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; 
/

Résultat:

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

Cela donne le premier et le dernier index de tous les éléments, pas le premier index d'un élément avec une valeur spécifique. L'OP veut savoir comment trouver l'index correspondant à la première apparition de, disons, 9 dans votre exemple, qui devrait retourner l'index numéro 3, avant ou après la suppression. –

+0

@AlexPoole: Merci, rien à dire :) –

6

Je ne suis pas sûr, si cela aide vraiment, ou si vous pensez qu'il est plus élégant:

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 errors 

drop type t_test; 
+0

Merci René. On dirait qu'il n'y a rien de intégré, alors je pourrais utiliser votre solution. '+ 1' mais pas encore accepté, car il ne répond pas vraiment à ma question :) –

2

Je ne pense pas qu'il y ait une fonction intégrée qui recherche une collection. Cependant, si vous savez que vous devrez beaucoup chercher dans une collection, vous pouvez créer un index. L'ajout d'un élément à la collection sera un peu plus cher, mais la recherche d'un élément sera une opération O (1) (au lieu de O (n) pour une recherche de force brute). Par exemple, vous pouvez utiliser quelque chose comme ceci:

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: 1 
B: 2 
C: 

PL/SQL procedure successfully completed 

Vous pouvez également définir un enregistrement contenant à la fois des tableaux et toutes les fonctions/procédures d'interagir avec des réseaux utiliseraient ce type d'enregistrement.

Questions connexes