2012-03-26 100 views
0

我想構建一個存儲過程來封裝一些複雜的邏輯。以下是基本代碼,有點匿名:爲什麼這個存儲過程返回一個空集?

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

是'LOOKUP_TABLE2.VALUE'可爲空場?因爲' NOT IN()'如果''的結果集包含NULL,則永遠不會成立。 (如果這是問題,那麼修正是將'和VALUE不爲空'添加到子查詢中。) – ruakh 2012-03-26 18:01:11

+0

@ruakh:不,兩個查找表都有NOT NULL約束。就像我說的那樣,查詢在邏輯上是正確的;當我將它作爲存儲過程運行時,它不會運行任何結果。 – 2012-03-26 18:02:35

+1

@Mason會很好,如果你發佈DDL statemenst這些表和一些示例數據,所以我們可以重新創建它 - SP似乎是好的 – JustMe 2012-03-27 06:45:41

回答

0

您正在將此視爲可選過程,但Firebird並未將此視爲可選過程,而是作爲可執行過程。如果你在最後添加一個SUSPEND它將會和AFAIK一樣解決你的問題。

+0

沒有。我試過了,但沒有奏效。我會更新這個問題。 – 2012-03-26 18:30:11

+0

[本頁](http://www.destructor.de/firebird/storedproc.htm)意味着'SUSPEND'實際上應該在* SELECT之前? – ruakh 2012-03-26 18:49:32

+0

@ruakh'SUSPEND'「打印」返回變量,並在選擇之前它們是空的 – JustMe 2012-03-27 07:11:39

0

SUSPEND就像一個倒立的FETCH它意味着「作爲結果發送一行」。

如果在SUSPEND中添加4行,來自GET_DATA(參數)的select *的結果應該至少有四行,其值爲空值。這意味着你的select語句不返回任何行,或者返回一個空值的行。

用簡單的查詢做一些測試。

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

2

你的程序總是返回1個結果即使選擇返回1或0的結果,因爲掛起是獨立選擇的。

爲了獲得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

1或0 **結果** - 不錯:) – JustMe 2012-03-27 08:17:33

+0

但我並不總是得到1結果;當我運行這個查詢時,我總是得到一個空集(0個結果)。把它變成一個for循環,這沒有幫助。 – 2012-03-27 17:20:04

相關問題