【发布时间】:2012-04-10 05:59:37
【问题描述】:
我正在尝试构建一个存储过程来封装一些复杂的逻辑。这是基本代码,稍微匿名:
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),使用相同的参数,我会得到一个空的结果集。
所以在存储过程级别出了点问题。任何人都知道它是什么以及如何解决它?
【问题讨论】:
-
LOOKUP_TABLE2.VALUE是可以为空的字段吗?因为如果<subquery>的结果集包含NULL,<value> NOT IN (<subquery>)永远不会为真。 (如果这是问题所在,那么解决方法是将and VALUE is not null添加到子查询中。) -
@ruakh:不,两个查找表都有 NOT NULL 约束。就像我说的,这个查询在逻辑上是正确的;当我将它作为存储过程运行时,它只是没有运行任何结果。
-
@Mason 如果您为这些表和一些示例数据发布 DDL 声明会很好,以便我们重新创建它 - SP 似乎没问题
-
这可能是转换问题吗?例:QO表的X、Y、W列是否也定义为
INTEGER?您是否在 SP 上将变量更改为值,而不是在 Firebird Maestro 上尝试选择权?
标签: sql stored-procedures firebird