2011-01-27 9 views
6

Esiste una funzione incorporata per determinare l'indice (primo) di un elemento in una raccolta PL/SQL?Ottenere l'indice dell'elemento nella raccolta PL/SQL

Qualcosa di simile

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: 

posso usare array associativi, tabelle nidificate o Varrays, qualunque necessario. Se lo stesso elemento esiste più di una volta, allora l'indice della prima occorrenza è sufficiente.


Altrimenti avrei dovuto fare qualcosa di simile

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; 

risposta

0

In caso di dubbio, consultare la documentazione;) (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; 
/

Risultato:

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

Questo sta dando il primo e l'ultimo indice di tutti gli elementi, non il primo indice di un elemento con un valore specifico. L'OP vuole sapere come trovare l'indice corrispondente alla prima apparizione di, diciamo, 9 nel tuo esempio, che dovrebbe restituire il numero indice 3, prima o dopo la cancellazione. –

+0

@AlexPoole: Grazie, non è rimasto nulla da dire :) –

6

Non sicuro, se questo aiuta veramente, o se si pensa che è più elegante:

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

Grazie René. Sembra che non ci sia nulla di built-in, quindi potrei usare la tua soluzione. '+ 1' ma non lo si accetta ancora, dal momento che non risponde alla mia domanda :) –

2

Io non credo che ci sia una funzione built-in che cerca una collezione. Tuttavia, se sai che dovrai cercare molto una collezione, potresti creare un indice. Aggiungere elementi alla raccolta sarà un po 'più costoso, ma la ricerca di un elemento sarà un'operazione O (1) (invece di O (n) per una ricerca forza bruta). Ad esempio, si potrebbe usare qualcosa di simile:

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 

Si potrebbe anche definire un record che contiene entrambi gli array e tutte le funzioni/procedure per interagire con gli array avrebbero usato questo tipo di record.

Problemi correlati