Из документации по явным курсорам (выделение добавлено):
Нельзя назначить значение явному курсору, использовать его в выражении, или использоватьэто как формальный параметр подпрограммы или переменная хоста. Вы можете сделать это с помощью переменной курсора (см. « Переменные курсора »).
Таким образом, вы не можете отправить явный курсор, c1
или c2
в вашем примере- у вас не может быть процедуры, которая принимает явный аргумент курсора.
Вам разрешено указывать ref курсор в качестве формального параметра , как вы уже делаете,Это может быть открытый курсор, как у вас;или переменная курсора, которую вы затем открываете. Но на самом деле вы не хотите, чтобы курсор находился вне вызова процедуры, поэтому ни один из них не выглядит вполне тем, что вам нужно.
Если бы у вас был определенный список курсоров с небольшим количеством символов, вы могли бы буквально передать имя курсора в виде строки, а затем используйте оператор case в процедуре, чтобы открыть соответствующий предопределенный курсор:
PROCEDURE outer_proc AS
m VARCHAR2(2000):='';
CURSOR c1 IS SELECT first_name,last_name FROM employees WHERE salary<1000;
CURSOR c2 IS SELECT first_name,last_name FROM employees WHERE salary>=1000;
PROCEDURE inner_proc(cur_name IN varchar2,m OUT VARCHAR2) IS
col1 VARCHAR2(20);
col2 VARCHAR2(20);
BEGIN
CASE cur_name
WHEN 'c1' THEN
OPEN c1;
LOOP
FETCH c1 INTO col1,col2; -- this will only work in the cursor only selects two columns!
EXIT WHEN c1%NOTFOUND;
m:=m||col1||' '||col2;
END LOOP;
CLOSE c1;
WHEN 'c2' THEN
OPEN c2;
LOOP
FETCH c2 INTO col1,col2; -- this will only work in the cursor only selects two columns!
EXIT WHEN c2%NOTFOUND;
m:=m||col1||' '||col2;
END LOOP;
CLOSE c2;
END CASE;
END;
BEGIN
inner_proc('c1',m);
inner_proc('c2',m);
END;
/
... но это не масштабируется и, возможно, уже хуже, чем чтотеперь у вас есть.
Или передайте курсор запрос вместо курсора в процедуру, а затем откройте и обработайте его с помощью динамического SQL. Так как именно это продемонстрировал @Wernfried, я не буду вдаваться в подробности. Возможный недостаток этого заключается в том, что если у вас уже есть явный курсор, который вы пытаетесь использовать повторно, то теперь вы дублируете этот запрос. Да, и поскольку он динамический, сам запрос не будет проанализирован до времени выполнения, поэтому ошибка может быть перехвачена не так рано, как хотелось бы.
TL; DR - см. @ Wernfried'sответ * 8 -)