Oracle Sys Refcurser в функции

У меня возникли проблемы с возвратом указателя на запрос.

Вот мой текущий код:

create or replace procedure getRoute(route IN varchar, routeday IN varchar)
  return sys_refcursor is
  v_rc sys_refcursor;
begin
    select DISTINCT BBT_JOURNEYSTOPS.SERVICE "Service", BBT_JOURNEYSTOPS.STOP_REFERENCE "StopNo", 
  STOP_NAME "Near", BBT_STOPS.ROAD_NAME "On", BBT_JOURNEYSTOPS.JOURNEYTIME "Duration"    
    from BBT_JOURNEYSTOPS
    inner join BBT_WEEKLYSCHEDULE
    on BBT_WEEKLYSCHEDULE.SERVICE = BBT_JOURNEYSTOPS.SERVICE
    inner join BBT_STOPS
    on BBT_JOURNEYSTOPS.STOP_REFERENCE = BBT_STOPS.STOPREF
    where  (UPPER(BBT_JOURNEYSTOPS.SERVICE) LIKE UPPER('%'|| :route || '%')) AND 
      (TO_NUMBER(SUBSTR(BBT_WEEKLYSCHEDULE.TIMEUNTIL, 1, 2)) > TO_NUMBER(TO_CHAR(SYSDATE, 'HH24')))
    ORDER BY BBT_JOURNEYSTOPS.SERVICE, BBT_JOURNEYSTOPS.JOURNEYTIME;


  return timetable;
end;
/

DECLARE
 rc refcursor;
BEGIN
  exec :rc := getRoute(:route, :routeday);
END;

Я получаю синтаксическую ошибку в первой строке, говорящую «Ожидаемый AUTHID, EXTERNAL». Однако я также не уверен, что код, который я написал, будет выполняться правильно. Любые подсказки или советы будут с благодарностью.


person Craig    schedule 22.04.2015    source источник
comment
возможный дубликат Ошибка печати переменной REFCURSOR как Параметр OUT в процедуре Oracle 11g   -  person Lalit Kumar B    schedule 22.04.2015
comment
Вы смешиваете процедуру с функцией. Либо создайте функцию для возврата курсора ссылки, либо создайте процедуру с курсором ссылки в качестве параметра OUT.   -  person Lalit Kumar B    schedule 22.04.2015


Ответы (2)


Документацию Oracle для синтаксиса CREATE PROCEDURE можно найти здесь.

CREATE PROCEDURE не имеет предложения возврата (то есть для FUNCTIONs); вместо этого вы должны использовать параметр OUT и удалить оператор return в конце.

Вам также необходимо использовать OPEN cursor_name FOR для выполнения запроса SELECT и связать его с курсором.

Кроме того, вам не нужно : перед переменными, объявленными в заголовке процедуры. Синтаксис :name предназначен для привязки переменных в SQL — PL/SQL автоматически обрабатывает привязку переменных без этого синтаксиса.

(Кажется, вы не используете аргумент routeday, поэтому вы можете удалить его, если не собираетесь использовать его в будущем).

Что-то вроде этого:

create or replace procedure getRoute(
  in_route      IN  varchar,
  in_routeday   IN  varchar,
  out_cursor    OUT SYS_REFCURSOR
)
is
begin
    OPEN out_cursor FOR
    select DISTINCT BBT_JOURNEYSTOPS.SERVICE "Service",
                    BBT_JOURNEYSTOPS.STOP_REFERENCE "StopNo",
                    STOP_NAME "Near",
                    BBT_STOPS.ROAD_NAME "On",
                    BBT_JOURNEYSTOPS.JOURNEYTIME "Duration"    
    from BBT_JOURNEYSTOPS
         inner join BBT_WEEKLYSCHEDULE
         on BBT_WEEKLYSCHEDULE.SERVICE = BBT_JOURNEYSTOPS.SERVICE
         inner join BBT_STOPS
         on BBT_JOURNEYSTOPS.STOP_REFERENCE = BBT_STOPS.STOPREF
    where  (UPPER(BBT_JOURNEYSTOPS.SERVICE) LIKE UPPER('%'|| in_route || '%'))
    AND    (TO_NUMBER(SUBSTR(BBT_WEEKLYSCHEDULE.TIMEUNTIL, 1, 2)) > TO_NUMBER(TO_CHAR(SYSDATE, 'HH24')))
    ORDER BY BBT_JOURNEYSTOPS.SERVICE, BBT_JOURNEYSTOPS.JOURNEYTIME;
end;
/

Вы также можете рассмотреть возможность использования строго типизированного курсора вместо слабого курсора.

Вы можете назвать это так:

DECLARE
  route VARCHAR2 := 'abc';
  routeday VARCHAR2 := 'Tuesday';
  rc SYS_REFCURSOR;
BEGIN
  getRoute(
    in_route    => route,
    in_routeday => routeday,
    out_cursor  => rc
  );
END;
/

Или, если вы хотите использовать переменные связывания (вне блока PL/SQL):

VARIABLE route VARCHAR2;
VARIABLE routeday VARCHAR2;
VARIABLE rc REFCURSOR;

BEGIN
  route := 'abc';
  routeday := 'Tuesday';
END;
/    

BEGIN
  getRoute(
    in_route    => :route,
    in_routeday => :routeday,
    out_cursor  => :rc
  );
END;
/

PRINT :rc;
person MT0    schedule 22.04.2015
comment
О, потрясающе, это действительно полезно! Большое спасибо :) - person Craig; 22.04.2015
comment
Когда я пытаюсь вызвать процедуру, я получаю следующее сообщение об ошибке: Отчет об ошибке — ORA-06550: строка 4, столбец 9: PLS-00222: в этой области не существует функции с именем «GETROUTE» ORA-06550: строка 4 , столбец 3: PL/SQL: Оператор проигнорирован 06550. 00000 - строка %s, столбец %s:\n%s *Причина: Обычно ошибка компиляции PL/SQL. *Действие: - person Craig; 22.04.2015
comment
Я использую этот код для вызова процедуры: DECLARE rc SYS_REFCURSOR; BEGIN rc := getRoute(:route, :routeday, rc); КОНЕЦ; - person Craig; 22.04.2015
comment
Есть идеи, почему он говорит, что не может найти процедуру? - person Craig; 22.04.2015
comment
Скомпилировалось без ошибок? (запустите SHOW ERRORS после CREATE PROCEDURE для проверки). В противном случае вы звоните ему от того же пользователя? - person MT0; 22.04.2015
comment
Удалось исправить ошибку - очень пригодился ваш код для печати результата :) Спасибо! - person Craig; 22.04.2015

Вы должны использовать OPEN FOR синтаксис и функцию вместо процедуры, а также : не требуется в основном коде для параметров

create or replace function getRoute(route IN varchar, routeday IN varchar)
  return sys_refcursor is
  v_rc sys_refcursor;
begin
    open v_rc  FOR
    select DISTINCT BBT_JOURNEYSTOPS.SERVICE "Service", BBT_JOURNEYSTOPS.STOP_REFERENCE "StopNo", 
  STOP_NAME "Near", BBT_STOPS.ROAD_NAME "On", BBT_JOURNEYSTOPS.JOURNEYTIME "Duration"    
    from BBT_JOURNEYSTOPS
    inner join BBT_WEEKLYSCHEDULE
    on BBT_WEEKLYSCHEDULE.SERVICE = BBT_JOURNEYSTOPS.SERVICE
    inner join BBT_STOPS
    on BBT_JOURNEYSTOPS.STOP_REFERENCE = BBT_STOPS.STOPREF
    where  (UPPER(BBT_JOURNEYSTOPS.SERVICE) LIKE UPPER('%'|| route || '%')) AND 
      (TO_NUMBER(SUBSTR(BBT_WEEKLYSCHEDULE.TIMEUNTIL, 1, 2)) > TO_NUMBER(TO_CHAR(SYSDATE, 'HH24')))
    ORDER BY BBT_JOURNEYSTOPS.SERVICE, BBT_JOURNEYSTOPS.JOURNEYTIME;


  return v_rc ;
end;

/

Также вы не можете использовать EXEC в коде pl\sql.

DECLARE
 rc refcursor;
BEGIN
  :rc := getRoute(:route, :routeday);
END;
person Ilia Maskov    schedule 22.04.2015
comment
Спасибо за помощь, но, к сожалению, я все еще получаю синтаксическую ошибку, как упоминалось ранее. - person Craig; 22.04.2015
comment
Это в Oracle SQL Developer. Я думаю, что другой человек, ответивший на этот вопрос, разобрался с ним - это потому, что я использовал процедуру, но использовал линию возврата! - person Craig; 22.04.2015
comment
Как я сказал в своем ответе, вы должны использовать FUNCTION с RETURN. И удалите exec в коде PLSQL. - person Ilia Maskov; 22.04.2015