2011-02-01 11 views
6

Mam procedurę w Oracle, która ma parametr varchar2. Na podstawie wartości tego parametru muszę zdefiniować kursor. Kursor będzie działał na różnych tabelach w oparciu o wartość parametru.Warunkowo zdefiniuj kursor

Chciałem zrobić coś takiego jak poniżej, ale powoduje to błąd w kodzie definicji CURSOR. Jakieś pomysły?

PROCEDURE GET_RECORDS(v_action IN VARCHAR2) 
IS 
CURSOR get_records 
IS 
     IF(v_action = 'DO THIS') THEN 
      SELECT * from <THIS>; 
     ELSE 
      SELECT * from <THAT>; 
     END IF; 
BEGIN 
     OPEN get_records; 

     FETCH get_records 
     INTO v_thing; 

     v_loop := 0; 
     WHILE get_records%FOUND 
     LOOP 

      FETCH get_records 
      INTO v_thing; 

     END LOOP; 
     CLOSE get_records; 
END; 

Odpowiedz

8

trzeba będzie REF CURSOR i otwórz go conditionaly, na przykład:

SQL> CREATE OR REPLACE PROCEDURE GET_RECORDS(v_action IN VARCHAR2) IS 
    2  v_thing  VARCHAR2(10); 
    3  get_records SYS_REFCURSOR; 
    4 BEGIN 
    5  IF (v_action = 'DO THIS') THEN 
    6  OPEN get_records FOR 
    7   SELECT 1 FROM dual; 
    8  ELSE 
    9  OPEN get_records FOR 
10   SELECT 2 FROM dual; 
11  END IF; 
12 
13  LOOP 
14  FETCH get_records INTO v_thing; 
15  EXIT WHEN get_records%NOTFOUND; 
16  /* do things */ 
17  dbms_output.put_line(v_thing); 
18  END LOOP; 
19  CLOSE get_records; 
20 END; 
21/

Procedure created 

SQL> exec get_records ('DO THIS'); 
1 

PL/SQL procedure successfully completed 

SQL> exec get_records ('DO THAT'); 
2 

PL/SQL procedure successfully completed 
+0

@Vincent ... to jest bomba !!! Działa świetnie ... Dziękuję – MikeTWebb

2

to pewnie kod coś takiego (gdzie dwie pętle może wezwać te same funkcje)

BEGIN 
    IF(v_action = 'DO THIS') 
    THEN 
    FOR this_cur IN (SELECT * FROM <THIS>) 
    LOOP 
     <<do something>> 
    END LOOP; 
    ELSE 
    FOR that_cur IN (SELECT * FROM <THAT>) 
    LOOP 
     <<do something else>> 
    END LOOP; 
    END IF; 
END; 

Można też użyć dynamicznego SQL, aby otworzyć kursor ale ma tendencję do bardziej skomplikowane, szczególnie, jeśli istnieją tylko dwie opcje.

IS 
    get_records SYS_REFCURSOR; 
    l_sql_stmt VARCHAR2(100); 
BEGIN 
    IF(v_action = 'DO THIS') 
    THEN 
    l_sql_stmt := 'SELECT * from <THIS>'; 
    ELSE 
    l_sql_stmt := 'SELECT * from <THAT>'; 
    END IF; 

    OPEN get_records FOR l_sql_stmt; 
    ... 
1

Można nawet użyć warunku wewnątrz niejawny dla pętli. Bez deklaracji kursora lub SYS_REFCURSOR (lubię ich przepraszam) - to znaczy można używać zmiennych, tu v_action niejawny, wewnątrz deklaracji kursora:

BEGIN 
    FOR this_cur IN (
     SELECT * FROM <THIS> 
     WHERE v_action = 'DO THIS' 
    ) LOOP 
     <<do something>> 
    END LOOP; 
    FOR that_cur IN (
     SELECT * FROM <THIS> 
     WHERE v_action <> 'DO THIS' 
    ) LOOP 
     <<do something else>> 
    END LOOP; 
    END IF; 
END;