web-dev-qa-db-fra.com

Évaluation des variables Boolean PL / SQL sur les formes Oracle

Supposons que j'ai une variable BOOLEAN dans un bloc PL/SQL dans une forme Oracle:

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

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

Après avoir parcouru ce code plusieurs fois avec un débogueur, j'ai déterminé que raise_my_error()jamais est appelée. Clarifier:

  • raise_my_error() fait non est appelé si is_viewable = TRUE
  • raise_my_error() fait non est appelé si is_viewable = FALSE

Les premiers tests suggèrent que ce comportement est limité au code PL/SQL exécuté dans les formulaires Oracle et non de code PL/SQL exécuté directement dans la base de données (bien que je puisse me tromper).

Je peux me contenter de comparer explicitement is_viewable À FALSE:

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

Je suis toujours curieux pourquoi NOT is_viewable Ne jamais évaluer à TRUE.

Mise à jour : Il apparaît que mon débogueur n'apparaissait pas les valeurs correctes et que cette question n'est plus valide. Désolé pour cette confusion.

12
Adam Paynter

Nous pouvons tester cela dans SQLPlus pour voir ce qui se passe dans chacune des 3 situations (vrai, faux, 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;
/

Qui produit:

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>

Donc, le seul chemin de code possible pouvant produire votre sortie attendue est si la valeur dans le conditionnel est fausse. Si ce n'est pas ce que vous voyez ou attendez, alors quelque chose d'autre doit se produire dans votre procédure ou comme effet secondaire.

15
Doug Porter

NOT is_viewable Évalue à TRUE si et seulement si is_viewable est FALSE.

Dans ton cas, is_viewable est probablement défini sur NULL; Peut-être que le débogueur des formulaires vous montre "False" dans ce scénario, ce qui provoque une confusion.

Essayez ce code à la place:

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

Quelle valeur la variable est-elle réglée? Comprenez que si la valeur est null, le bloc ne s'exécutera jamais. Je ne sais pas si c'est votre problème, mais voici un exemple:

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;

Bien sûr, je ne sais pas comment les formes oracles le feraient différemment, mais peut-être que cela définit la variable à NULL en quelque sorte?

4
dcp

Vous devez définir une valeur initiale pour IS_Viewable lorsqu'il est déclaré. Oracle ne définit pas une valeur par défaut pour les booléens lorsqu'ils sont déclarés. Définissez la valeur du booléen lorsqu'il est déclaré définir la valeur à l'intérieur du bloc peut ne pas toujours être la meilleure idée. Si vous créez une fonction et que le bloc échoue, vous pouvez obtenir une fonction renvoyée sans valeur mais si elle est déclarée à l'extérieur du bloc et que vous avez un gestionnaire d'exception, il attraperait et gérerait l'erreur. C'est toujours une bonne pratique pour configurer le bloc de cette manière.

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 
2
devdar

Essayez ceci pour voir si cela change quelque chose:

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

Quelle est la version des formulaires?
[.____] Je viens d'essayer de suivre le code dans les formulaires Builder 6i et cela fonctionne comme prévu

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;

Est-ce que cela fonctionne dans votre environnement?

Edit Ajout de NULL à l'exemple.

1
Alexander Malakhov