我正在尝试构建一个存储过程来封装一些复杂的逻辑。这是基本代码,稍微匿名:
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)
,使用相同的参数,我会得到一个空的结果集。
因此存储过程级别出现问题。任何人都知道它是什么以及如何解决它?
答案 0 :(得分:2)
即使选择返回1或0结果,您的程序也始终返回1结果,因为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 ; ^
答案 1 :(得分:0)
您将此视为可选择的过程,但Firebird并未将此视为可选过程,而是将其视为可执行过程。如果你在最后添加SUSPEND
,那么AFAIK应该可以解决你的问题。
答案 2 :(得分:0)
SUSPEND
就像倒置的FETCH
,意思是“发送一行作为结果”。
如果使用SUSPEND添加4行; select * from GET_DATA(参数)的结果应至少为四行,且值为null。这意味着您的select语句没有返回任何行,或者一行返回空值。
使用更简单的查询进行一些测试。
select 1, 'TEST' from RDB$DATABASE into :ID, :NAME;