Ошибка «Курсор уже открыт», когда я пытаюсь выполнить свою процедуру в Oracle SQL - PullRequest
1 голос
/ 30 октября 2019

Я написал функцию в oracle sql для извлечения имени сотрудника, чей идентификатор в таблице соответствует вводу, данному для этой функции.

 create or replace function id_search
    (
    x in number
    )
    return number
    is
    cursor e is select ename from employee where emp_id = x;
    begin
    open e;
   for i in e
   loop
   dbms_output.put_line('name is :'||i.ename);
   end loop;
   close e;
   return 0;
   end;
   /

После этого я вызвал эту функцию в процедуре Iнаписал:

SQL>     create or replace procedure id_searchP
  2      (
  3      y in number
  4      )
  5      is
  6      t number:= 1;
  7      begin
  8      t := id_search(y);
  9      end;
 10      /

Однако, когда я пытаюсь выполнить свою процедуру, я сталкиваюсь с ошибкой:

SQL> exec id_searchP(2);
BEGIN id_searchP(2); END;

          *

ERROR at line 1:
ORA-06511: PL/SQL: cursor already open
ORA-06512: at "tom.ID_SEARCH", line 7
ORA-06512: at "tom.ID_SEARCH", line 10
ORA-06512: at "tom.ID_SEARCHP", line 8
ORA-06512: at line 1

Почему я получаю эту ошибку?

Ответы [ 3 ]

2 голосов
/ 31 октября 2019

Очень редко вам нужно использовать явно объявленный курсор. Привыкайте использовать циклы FOR для курсора:

 create or replace function id_search(pinEmployee_ID in number)
    return number
 is
 begin
   for rowEmployee in (select ename
                         from employee
                         where emp_id = pinEmployee_ID)
   loop
     dbms_output.put_line('name is :' || rowEmployee.ename);
   end loop;

   return 0;
 end id_search;

Там - короче, проще, менее подвержен ошибкам и проще для понимания.

Пожалуйста, используйте значимые имена. Мне все равно, если это школьное задание или что-то еще - используйте значимые имена. Не заставляйте людей копаться в вашем коде, чтобы выяснить, что означают или для чего используются ваши параметры.

Далее - пожалуйста, найдите время, чтобы отформатировать ваш код, чтобы он был читабельным. Делайте последовательные отступы, следите за тем, чтобы уровни кода были видны невооруженным глазом, вставляйте пробелы, чтобы ваш код можно было легко прочитать, правильно написать и разобрать. Я не хочу видеть i для имени параметра - если то, что передается, является (должно быть) идентификатором сотрудника, то убедитесь, что имя параметра делает это очевидным. Компьютерное программирование - это прежде всего упражнение в общении - между вами, компьютером и бедным тупым SOB, который через десять лет должен будет прочитать ваш код и выяснить, что он делает. Не будьте парнем, на которого все ругаются, когда им приходится поддерживать ваш код. Развивайте хорошие привычки сейчас.

Программирование - это ремесло. Если это то, что вы действительно хотите сделать, работайте над тем, чтобы делать это хорошо. Каждое задание, каждый сценарий, каждый день - это возможность совершенствования. Или, по крайней мере, показать, что вы знаете. Убедитесь, что то, что вы показываете, всегда самое лучшее.

2 голосов
/ 30 октября 2019

Вы открываете и закрываете курсор два раза. Вам не нужно open e;, а затем снова for i in e. Мне нравится это в вашей функции:

create or replace function id_search(x in number)
return number
is

    cursor e 
    is
    select ename 
    from employee 
    where emp_id = x;

begin

       for i in e loop
          dbms_output.put_line('name is :'||i.ename);
       end loop;

       return 0;
end;

Тогда процедура в порядке:

create or replace procedure id_searchP(y in number)
is
     t number:= 1;
begin
     t := id_search(y);
end;

И тогда будет достаточно только одного вызова:

BEGIN 
  id_searchP(2); 
END;

Вот это ДЕМО

1 голос
/ 30 октября 2019

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

Если вы хотите использовать курсор для цикла, вам необходимо удалить явные операторы открытия и закрытия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...