Justification du LNNVL


12

LNNVL est une fonction Oracle intégrée qui renvoie VRAI pour les conditions évaluées à FAUX ou INCONNU, et renvoie FAUX pour les conditions évaluées à VRAI. Ma question est quel serait l'avantage de retourner l'opposé de la condition de vérité plutôt que de simplement gérer les valeurs NULL?

Par exemple, supposons que vous ayez une table Emp avec des colonnes StartCommission et CurrentCommission qui peuvent contenir des valeurs NULL. Ce qui suit ne renvoie que des lignes sans aucune valeur null:

SELECT * FROM Emp WHERE StartCommission = CurrentCommission;

Si vous vouliez inclure des lignes où l'une ou l'autre des commissions est nulle, vous pourriez faire quelque chose comme ceci:

SELECT * FROM Emp WHERE StartCommission = CurrentCommission 
OR StartCommission IS NULL OR CurrentCommission IS NULL;

Il semblerait qu'une fonction existerait pour raccourcir cette syntaxe, mais l'utilisation de LNNVL renvoie tous les enregistrements non égaux et tous les enregistrements avec des valeurs NULL.

SELECT * FROM Emp WHERE LNNVL(StartCommission = CurrentCommission);

L'ajout de NOT à cela ne renvoie que des lignes sans null. Il me semble que la fonctionnalité souhaitée pour ce cas serait de garder les vraies conditions vraies, les fausses conditions fausses et d'avoir des conditions inconnues évaluées comme vraies. Ai-je vraiment créé un cas d'utilisation faible ici? Est-il vraiment plus susceptible de vouloir transformer l'inconnu en vrai, le vrai en faux et le faux en vrai?

create table emp (StartCommission Number(3,2), CurrentCommission Number(3,2));
insert into emp values (null,null);
insert into emp values (null,.1);
insert into emp values (.2,null);
insert into emp values (.3,.4);

Aujourd'hui, j'ai rencontré LNNVL et j'essaie de découvrir ou de comprendre également cette partie "quel serait l'avantage de retourner le contraire de la vérité". Cependant, l'instruction que vous utilisez pour illustrer LNNVL doit utiliser l'opérateur différent: SELECT * FROM Emp WHERE LNNVL (StartCommission <> CurrentCommission); de sorte qu'il renvoie le même résultat que l'instruction en utilisant ORs. En d'autres termes, si nous utilisons une condition et que nous voulons également inclure des lignes ayant une valeur NULL, nous devons transmettre la négation de notre condition à LNNVL.
Only You

Un autre exemple simple. Seuls les employés qui reçoivent effectivement une commission de moins de 20%: SELECT * FROM employés WHERE commission_pct <.2; Pour inclure également les employés qui ne reçoivent aucune commission: SELECT * FROM employés WHERE LNNVL (commission_pct> = .2);
Only You

@OnlyYou - Vous avez raison, pour que LNNVL fonctionne de la même manière, la condition doit être <>. Je l'ai laissé = plus parce que si la fonction retournait les mêmes résultats avec le signe = cela aurait plus de sens. Essentiellement, la fonction exécute deux actions 1. Inclusion nulle, 2. Bascule booléenne. La première a du sens, la dernière semble simplement confondre des choses nécessitant le contraire de la condition souhaitée. ie = requiert <>, <nécessite> =, etc.
Leigh Riffel

Réponses:


6

C'est une fonction étrange avec une histoire étrange - mais alors nvl2 est bizarre. lnnvlest fondamentalement un is not trueopérateur - sans aucun doute, il peut être utilisé à bon escient comme le nvl2peut, mais lorsque vous devez rechercher une fonction chaque fois que vous l'utilisez pour vous rappeler exactement ce qu'elle fait, vous vous demandez s'il vaut mieux s'en tenir à nvl, coalesce, decodeet nullifainsi que des caseexpressions, qui sont plus intuitifs


Je ne trouve pas NVL2 bizarre, mais je l'utilise beaucoup et je n'ai jamais utilisé LNNVL.
Leigh Riffel

@Leigh - Je suppose que vous devez l'utiliser juste assez souvent pour que cela ne devienne pas bizarre :) Je n'ai jamais utilisé nullifjusqu'à ce que je réalise que cela peut être d'une grande aide pour rendre la «division par zéro» = nulle. Trouvez-vous vraiment nvl2 (a, c, b) bien meilleur que décoder (a, null, b, c)?
Jack dit d'essayer topanswers.xyz

4

En d'autres termes, je n'ai pas encore utilisé LNNVL depuis plusieurs années en tant que programmeur DBA et PL / SQL. J'ai utilisé NVL2 à l'occasion (et j'ai toujours dû chercher quel côté était vrai et quel côté ne l'était pas). À ce stade, il semble préférable, du point de vue de la lisibilité, de finir par utiliser NVL, DECODE, CASE, etc.,

Alternativement, cela fonctionne, en supposant que l'on maîtrise bien la façon dont Oracle gère les valeurs NULL et l'arithmétique, mais à ce stade, on peut aussi bien utiliser votre requête d'origine pour la lisibilité (et le plan d'exécution peut également être plus dur):

/* Return all rows where StartCommission is the same
 * as Current Commission, or those rows who have a
 * NULL in either (including both)
 */

SELECT *
  FROM Emp
 WHERE StartCommission = CurrentCommission
    OR StartCommission + CurrentCommission IS NULL

-- NULL + NULL, or NULL + Number is always NULL; hence return either
-- those records that are equal, or have a combined total of NULL
-- (either or both fields will be NULL).

Tu veux dire StartCommission<>CurrentCommission OR StartCommission + CurrentCommission IS NULL?
Jack dit d'essayer topanswers.xyz

@JackPDouglas - C'est logique comme =.
Leigh Riffel

Variation intéressante. Je suis d'accord avec vos conclusions.
Leigh Riffel

@Leigh - Je vois, une alternative à la fonction que vous voulez, pas une alternative à lnnvl.
Jack dit d'essayer topanswers.xyz

@JackPDouglas - Je comprends et je pense que c'est ce que Kerri voulait.
Leigh Riffel
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.