Почему эта хранимая процедура возвращает пустой набор? - PullRequest
0 голосов
/ 26 марта 2012

Я пытаюсь создать хранимый процесс для инкапсуляции сложной логики.Вот основной код, немного анонимный:

SET TERM ^ ;

RECREATE PROCEDURE GET_DATA (
 USERID   INTEGER,
 W        INTEGER,
 X        INTEGER,
 Y        INTEGER)
RETURNS (
 ID       INTEGER,
 NAME     VARCHAR(64) CHARACTER SET UTF8)
AS 
BEGIN
  select first 1
    QP.ID,
    QO.NAME
  from QP
  join QO
    on QO.ID = QP.QO_ID
  where
    (QO.W = :w) and (QO.X = :x) and (QO.Y = :y)
    and ((QP.PREREQUISITE in (
      select VALUE
      from LOOKUP_TABLE1
      where USER_ID = :userid))
      or (QP.PREREQUISITE is null))
    and (QO.Q_ID not in (
      select VALUE
      from LOOKUP_TABLE2
      where USER_ID = :userid))
  order by QP.SEQUENCE desc
  into :ID, :NAME;
  suspend;
END^

SET TERM ; ^

Ожидается, что он вернет 1 или 0 результатов.Это логически правильно;если я беру запрос SELECT, подставляю параметры вручную и запускаю его в Firebird Maestro, он дает ожидаемый результат.Но если я скажу select ID, NAME from GET_DATA(1, 1, 2, 3) с теми же параметрами, я получу пустой набор результатов.

Так что на уровне хранимых процедур что-то идет не так.Кто-нибудь знает, что это такое и как я могу это исправить?

Ответы [ 3 ]

2 голосов
/ 27 марта 2012

Ваша процедура всегда возвращает 1 результат, даже если выборка возвращает 1 или 0 результатов, поскольку SUSPEND не зависит от выбора.

Чтобы получить 0 или 1, чтобы выбрать соответствующие результаты, вы можете использовать:

RECREATE PROCEDURE GET_DATA (
   USERID   INTEGER,
   W        INTEGER,
   X        INTEGER,
   Y        INTEGER)
  RETURNS (
   ID       INTEGER,
   NAME     VARCHAR(64) CHARACTER SET UTF8)
  AS
  BEGIN
    FOR select first 1
      QP.ID,
      QO.NAME
    from QP
    join QO
      on QO.ID = QP.QO_ID
    where
      (QO.W = :w) and (QO.X = :x) and (QO.Y = :y)
      and ((QP.PREREQUISITE in (
        select VALUE
        from LOOKUP_TABLE1
        where USER_ID = :userid))
        or (QP.PREREQUISITE is null))
      and (QO.Q_ID not in (
        select VALUE
        from LOOKUP_TABLE2
        where USER_ID = :userid))
    order by QP.SEQUENCE desc
    into :ID, :NAME DO
       suspend;
  END^

  SET TERM ; ^
0 голосов
/ 27 марта 2012

SUSPEND аналогично инвертированному FETCH, что означает «отправить строку в качестве результата».

Если вы добавите 4 строки с помощью SUSPEND;Результат вашего выбора * из GET_DATA (параметры) должен содержать не менее четырех строк с нулевыми значениями.Это означало бы, что ваш оператор select не возвратил ни строки, ни одну строку с нулевыми значениями.

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

select 1, 'TEST' from RDB$DATABASE into :ID, :NAME;

0 голосов
/ 26 марта 2012

Вы рассматриваете это как выбираемую процедуру, но Firebird воспринимает это не как выбираемую процедуру, а как исполняемую процедуру. Если вы добавите SUSPEND в конце, это будет, и AFAIK, который должен решить вашу проблему.

...