2009-12-09 115 views
11

假設我有一個Oracle表一個PL/SQL塊內的BOOLEAN變量:評估表

DECLARE 
    is_viewable BOOLEAN; 
BEGIN 
    is_viewable := ...; 

    IF NOT is_viewable THEN 
    raise_my_error(); // pseudo-code 
    END IF; 
END; 

通過這個代碼幾次調試器步進之後,我有確定raise_my_error()從來沒有被調用。爲了澄清:

  • raise_my_error()得到,如果is_viewable = TRUE
  • raise_my_error()被調用,如果is_viewable = FALSE

初步試驗表明,這種行爲被限制在PL/SQL代碼的運行叫在Oracle Forms中,而不是在數據庫中直接運行PL/SQL代碼(儘管我可能是錯的)。

我可以明確地比較is_viewableFALSE解決這個問題:

IF is_viewable = FALSE THEN 
    raise_my_error(); 
END IF; 

我仍然好奇,爲什麼NOT is_viewable從不計算TRUE

更新:看來我的調試器沒有顯示正確的值,並且此問題不再有效。對於這種困惑感到抱歉。

+0

[友情提示]因爲你是有經驗的用戶,我想你只是忘了接受一個答案(dcp's或Jeffrey's)。 –

+0

@AlexanderMalakhov:我有幾次想接受一個答案,但是現在問題似乎是無法回答的,因爲代碼似乎運行正常。除非我誤解了,否則答案都不能解釋爲什麼NOT_viewable'總是**評估爲FALSE(不管is_viewable的值如何),而is_viewable = FALSE將評估爲TRUE或' FALSE',取決於'is_viewable'的值。由於問題停止發生,我無法驗證任何答案。 :( –

+0

瞭解。我有類似的(「沒有正確答案,無法驗證」)[question](http://stackoverflow.com/questions/2233856/oracle-forms-6i-crashes-with-0xc0000005-at因爲其他人永遠不會回答我的Q,所以我決定接受*最有用的*(而不是正確的)回答。他的時間和努力,對於我的問題沒有在懸而未決的問題列表中懸而未決,雖然很清楚,我完全沒有問題,不跟隨我的策略的人(更重要的是,你顯然爲SO社區做了很棒的工作) –

回答

4

變量被設置爲什麼值?要明白,如果值爲null,塊將永遠不會執行。我不知道如果這是你的問題,但這裏有一個例子:

DECLARE 
is_viewable BOOLEAN; 
BEGIN 
    IF NOT is_viewable 
    THEN 
     /* this won't execute */ 
     dbms_output.put_line('nope'); 
    END IF; 
    IF is_viewable 
    THEN 
     /* neither will this */ 
     dbms_output.put_line('nope'); 
    END IF; 
END; 

當然,我不知道怎麼的Oracle Forms會做不同的,但也許它的設置變量以某種方式爲空?

+0

感謝您的提示!我已經理解了NULL值的問題,但是我目睹了這種行爲(通過調試器),其中'is_viewable'設置爲'TRUE',以及'is_viewable'設置爲'FALSE'。說實話,我沒有試過看到如果它被設置爲NULL,會發生什麼......我懷疑它會對情況有很大幫助。 –

4

NOT is_viewable評估爲TRUE當且僅當is_viewableFALSE

在你的情況下,is_viewable可能被設置爲NULL;在這種情況下,Forms調試器可能會顯示「FALSE」導致混淆。

試試這個代碼,而不是:

IF NOT is_viewable THEN 
    raise_my_error(); 
ELSIF is_viewable IS NULL THEN 
    raise_another_error(); 
END IF; 
1

試試這個,看看它改變任何東西:

IF is_viewable THEN 
    NULL; 
ELSE 
    raise_my_error(); 
END IF; 
+1

值得一提的是,這段代碼可能會隱藏錯誤。例如。 'myBool:=(sum1 = sum2)',其中'sum1 = 0'和'sum2爲null'。人們可能會希望這是「真」而不是零。 –

13

我們可以在sqlplus測試此看到在每個3分的情況下會發生什麼(真,假,空):

set serveroutput on 

declare 
    true_value boolean := true; 
    false_value boolean := false; 
    null_value boolean; 
begin 

    if not true_value then --Should not pass 
     dbms_output.put_line('True Value'); 
    end if; 

    if not false_value then --Should pass 
     dbms_output.put_line('False Value'); 
    end if; 

    if null_value is null then --Just to make sure it is null 
     dbms_output.put_line('Null Value is Null'); 
    end if; 

    if not null_value then --Should not pass 
     dbms_output.put_line('Null Value'); 
    end if; 
end; 
/

主要生產:

SQL> set serveroutput on 
SQL> 
SQL> declare 
    2 true_value boolean := true; 
    3 false_value boolean := false; 
    4 null_value boolean; 
    5 begin 
    6 
    7  if not true_value then --Should not pass 
    8  dbms_output.put_line('True Value'); 
    9  end if; 
10 
11  if not false_value then --Should pass 
12  dbms_output.put_line('False Value'); 
13  end if; 
14 
15  if null_value is null then --Just to make sure it is null 
16  dbms_output.put_line('Null Value is Null'); 
17  end if; 
18 
19  if not null_value then --Should not pass 
20  dbms_output.put_line('Null Value'); 
21  end if; 
22 end; 
23/
False Value 
Null Value is Null 

PL/SQL procedure successfully completed. 

SQL> 

所以唯一可能的代碼路徑可以產生您的預期輸出是如果進入條件的值是假的。如果這不是你所看到或期望的,那麼你的手術中必須發生其他事情,或者作爲副作用。

+0

很好解釋..謝謝 – artapart

1

Forms的版本是什麼?
我只是試着在表單生成器6I下面的代碼和它的作品如預期

DECLARE 
    bTest BOOLEAN; 
BEGIN 
    bTest := FALSE; 
    IF NOT bTest THEN 
     MESSAGE('NOT FALSE passed'); 
     PAUSE; 
    END IF; 

    bTest := TRUE; 
    IF bTest THEN 
     MESSAGE('TRUE passed'); 
     PAUSE; 
    END IF; 

    bTest := NULL; 
    IF bTest OR (NOT bTest) THEN 
     MESSAGE('You will never see this message'); 
     PAUSE; 
    END IF; 
END; 

這是否工作在您的環境?

編輯將null加入示例。

+0

是的,表單的版本會很有用。也是Oracle客戶端的版本。和數據庫。較早版本的Forms有自己的PL/SQL解釋器,可能會影響到您。 –

2

聲明時必須爲is_viewable設置初始值。聲明時,Oracle不爲BOOLEANS設置默認值。設置BOOLEAN的值時,聲明設置塊內的值可能並不總是最好的想法。如果您正在創建一個函數並且該塊失敗,那麼您可能會得到一個沒有值的函數,但是如果在塊外部聲明並且您有一個異常處理程序,那麼它將捕獲並處理該錯誤。以這種方式設置模塊總是一個很好的做法。

DECLARE 
    bTest BOOLEAN := FALSE; 

BEGIN 

--in your test check for the most likely thing that would happen 
--if bTest would in most instances evaluate to be FALSE then that should be your check 

    IF NOT bTest THEN 


    MESSAGE('True Passed'); 

    ELSE 

    MESSAGE('False Passed'); 


    END IF; 

--in the event that an exception occurs or the block fails 
--the function would still return a value 

EXCEPTION WHEN NO_DATA_FOUND THEN 
    bTest := FALSE; 

WHEN OTHERS THEN 
     bTest := FALSE; 


END