Условно определить курсор - PullRequest
7 голосов
/ 01 февраля 2011

У меня есть процедура в Oracle, которая принимает параметр varchar2. Основываясь на значении этого параметра, мне нужно определить курсор. Курсор будет работать с разными таблицами в зависимости от значения параметра.

Я хотел сделать что-то вроде ниже, но это выдает ошибку в определении кода CURSOR. Есть идеи?

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;

Ответы [ 3 ]

9 голосов
/ 01 февраля 2011

вам понадобится REF CURSOR и откройте его условно, например:

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
2 голосов
/ 01 февраля 2011

Я бы, вероятно, написал что-то вроде этого (где два цикла могут вызывать одинаковые функции)

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;

Вы также можете использовать динамический SQL для открытия курсора, но это может стать более сложным, особенно еслиЕсть только два варианта.

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 голос
/ 13 апреля 2017

Вы даже можете использовать условие внутри неявного цикла for.Без объявления курсора или SYS_REFCURSOR (мне это не нравится, извините) - я имею в виду, что вы можете использовать свои переменные, здесь v_action, внутри неявного объявления курсора:

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;
...