Sql 为什么此存储过程返回一个空集?
我试图构建一个存储过程来封装一些复杂的逻辑。以下是一些匿名的基本代码:Sql 为什么此存储过程返回一个空集?,sql,stored-procedures,firebird,Sql,Stored Procedures,Firebird,我试图构建一个存储过程来封装一些复杂的逻辑。以下是一些匿名的基本代码: 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 firs
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中运行它,它会给出预期的结果。但是如果我说使用相同的参数从GET_DATA(1,1,2,3)中选择ID,NAME
,我会得到一个空的结果集
所以在存储过程级别出现了一些问题。有人知道它是什么以及我如何修复它吗?您将其视为一个可选择的过程,但Firebird并不认为这是一个可选择的过程,而是一个可执行的过程。如果在最后添加一个
SUSPEND
,它会成功的,而且这会解决您的问题。SUSPEND
就像一个反向的FETCH
它的意思是“作为结果发送一行”
如果您添加了4行挂起;select*from GET_数据(参数)的结果应至少为四行空值。这意味着您的select语句没有返回任何行,或者有一行返回空值
使用更简单的查询进行一些测试
选择1,'TEST'从RDB$数据库进入:ID,:NAME代码>您的过程始终返回1个结果,即使select返回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 ; ^
LOOKUP\u table 2.VALUE
是否为可空字段?因为如果
的结果集包含NULL
,则不在()
中永远不可能为真。(如果这是问题所在,那么修复方法是将和VALUE not null
添加到子查询。)@ruakh:No,两个查找表都没有null约束。就像我说的,这个查询在逻辑上是正确的;当我将其作为存储过程运行时,它只是没有运行任何结果。@如果您为这些表和一些示例数据发布DDL statemenst,这样我们就可以重新创建它,Mason会很高兴的-SP似乎可以,您是否尝试在或中调试它?这可能是转换问题吗?例:QO表的X、Y和W列是否也定义为INTEGER
?您是否在SP中将变量更改为值,而不是在Firebird Maestro上尝试右选择?没有。我试过了,但没用。我会更新这个问题。表示挂起
实际上应该在选择
?@ruakh挂起
之前“打印”返回变量,然后在选择它们之前empty@ruakh不,如果仔细观察,第一次挂起将返回在循环外部初始化的值。@MarkRotterVeel:有趣的一点。我猜那个页面的作者只是被搞糊涂了。要么1个结果要么0个结果——很好:)但我并不总是得到1个结果;运行此查询时,我总是得到一个空集(0个结果)。像那样把它变成for循环也没用。