Оценка логических переменных PL/SQL в Oracle Forms

Предположим, что у меня есть переменная BOOLEAN в блоке PL/SQL в форме Oracle:

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_viewable с FALSE:

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

Мне все еще интересно, почему NOT is_viewable никогда не оценивает TRUE.

Обновление: Похоже, что мой отладчик не показывал правильные значения и этот вопрос больше недействителен. Прошу прощения за эту путаницу.

Ответ 1

Мы можем проверить это в SQLPlus, чтобы узнать, что происходит в каждой из трех ситуаций (true, false, null):

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>

Таким образом, единственный возможный путь кода, который может привести к вашему ожидаемому результату, - это если значение, входящее в условное значение, является ложным. Если это не то, что вы видите или ожидаете, тогда что-то еще должно происходить в вашей процедуре или в качестве побочного эффекта.

Ответ 2

Какое значение задается переменной? Поймите, что если значение равно 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 будет делать это по-другому, но, возможно, он каким-то образом установил переменную?

Ответ 3

NOT is_viewable оценивается TRUE тогда и только тогда, когда is_viewable есть FALSE.

В вашем случае is_viewable, вероятно, устанавливается в NULL; возможно, отладчик Forms показывает вам "FALSE" в этом сценарии, вызывая путаницу.

Попробуйте использовать этот код:

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

Ответ 4

Вы должны установить начальное значение для 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 

Ответ 5

Попробуйте это, чтобы увидеть, не изменилось ли это:

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

Ответ 6

Что такое версия форм?
Я только что попробовал следующий код в Forms Builder 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;

Это работает в вашей среде?

Изменить добавлен нуль, например.