0
votes

Pourquoi Oracle ne traite-t-il pas '' comme null dans un entre la comparaison NVL

J'ai cette requête, ne remplissant aucune donnée comme variables. Attendre une rangée; Je ne reçois rien.

select 1 from dual
where SYSDATE BETWEEN NVL('', SYSDATE) AND NVL('', SYSDATE)


4 commentaires

Je suis désolé - j'ai peut-être manqué quelque chose. Où dans votre première déclaration avez-vous eu '' ? Aussi - '' n'est pas toujours la même chose que null. Considérez ce qui se passe lorsque vous assignez '' à une variable de caractère. Hmmm... :-)


Lorsque vous avez exécuté votre test, quel programme Front-End (Client Interface) avez-vous utilisé? En particulier, ni le développeur SQL * Plus ni SQL ne prend en charge le type de données de date pour les variables de liaison. Si vous passez dans null il est interprété comme une chaîne null. Comment passeriez-vous des dates qui ne sont pas nuls avec ce code que vous avez? Passez-vous dans des cordes et espère que le NLS_Date_Format est juste juste? Je parie si vous avez pu passer du type de données de date réel, vous obtiendriez le résultat attendu - mais vous ne pouvez pas le faire dans le développeur SQL * Plus ou SQL.


Vous avez certainement démontré que SQL (ou au moins la mise en œuvre d'Oracle) n'est pas composable.


J'utilise le crapaud que l'outil de développeur et l'APEX, tout comme ce que cette déclaration se déroule.


4 Réponses :


1
votes

Ce que vous ne savez pas que vous ne vous tuerez pas. C'est "ce que tu sais", ce n'est tout simplement pas si ...

La raison pour laquelle Oracle ne traite pas '' ' comme null est parce que ' ' n'est pas Un null - c'est une chaîne de longueur nulle constante. Maintenant, ici, les gens vont sauter et me dire que je me trompe, et que je ne sais pas de quoi je parle et interroge ma filiation, et commence probablement à une pétition pour nier ma sécurité sociale et me donner un coup de pied hors de la vieille maison de pet, mais j'ai raison. Voici une démonstration: xxx

maintenant sans regarder en bas (oui, je sais - c'est dur. Essayez ... :-) Quelle sortie faire Vous attendez du code ci-dessus? Si vous êtes comme la plupart des gens (y compris moi, jusqu'à ce que je fût trébuché il y a quelques années), vous vous attendriez à ce que ce soit: xxx

c'est-à-dire que vous Attendez-vous à la fonction pour renvoyer NULL lorsqu'il est appliqué à toutes ces variables - car ils devraient tous être nuls, non?

Mais ce n'est pas ce que vous obtenez ( Voir ce dB <> Fiddle ). Ce que vous réellement get est: xxx

whoa! Attendre!! Qu'est-ce que 10 faire là-bas?!?

Eh bien, c'est assez simple. Pensez à la sémantique du type de données Char Pl / SQL. Si vous attribuez une chaîne à une variable ou champ de code> char , et la longueur de la chaîne attribuée est plus courte que la longueur définie de la variable ou du champ, la valeur attribuée à la variable ou au champ est rembourrée sur le droit à la largeur définie complète de la variable / champ - dans ce cas, 10 caractères. Donc, lorsqu'un '' - c'est-à-dire une constante de chaîne de longueur zéro - est attribuée à la variable cstr , la valeur attribuée à la variable est rembourrée à droite au droit au droit Largeur définie de la variable, donc cstr finit par 10 blancs. Mais quand une null est affectée à la même variable de caractère, elle finit par être réglée sur NULL, comme prévu, et la fonction renvoie NULL, comme prévu.

La sémantique de Varchar2 (Et, pour le moment, Varchar - au moins jusqu'à ce que Oracle se contente de soutenir la sémantique ANSI pour Varchar, qu'ils vont faire très bientôt (TM)) sont différents dans Oracle. Lorsqu'une variable / champ de type varchar2 est attribuée une valeur, elle ne fait aucun rembourrage; Au lieu de cela, il attribue uniquement les caractères significatifs de la chaîne source à la variable ou sur le champ, et si la longueur résultante de la chaîne attribuée à la variable est zéro, la variable ou le champ est défini sur NULL, conformément à la règle Oracle qui " Les valeurs de chaîne de longueur zéro sont les mêmes que NULL ". Mais cela se produit au moment où la valeur est attribuée à la variable. '' seul est toujours une constante de chaîne de longueur zéro.

rappelez-vous - ce n'est pas ce que vous ne savez pas que vous ne savez pas que vous ne vous tuerez pas. C'est "ce que tu sais" ce n'est pas le cas ...: -)


3 commentaires

Très long explication qui n'a absolument rien à voir avec la question de l'OP. Sa question était de 100% dans le contexte SQL. Votre démo est PL / SQL. Dans SQL uni, Sélectionnez la longueur (coulée ('' comme Char (10))) à partir de Dual; Retours NULL , pas 10 . Et, dans tous les cas, une réponse dans ces lignes devrait d'abord indiquer que - très probablement - l'OP ne passe pas dans un null date à la requête, mais d'autres données taper.


Il y a, à la manière, très simple et directe des manières directes dans lesquelles la plaine Oracle SQL traite '' ' comme une chaîne vide, pas comme true null - peut-être l'exemple le plus simple est le traitement en concaténation.


Comme indiqué dans ma question initiale, [Sélectionnez 1 de Dual où '' est NULL] Retourne une ligne. Donc, Oracle traite '' comme null à cet égard.



0
votes

Le problème est que certaines interfaces utilisateur (y compris, gênant, SQL * Plus et SQL Developer) ne prennent pas en charge le type de données de date pour les variables de liaison.

Ceci est une limitation de ces interfaces utilisateur. Oracle SQL est parfaitement capable de travailler avec des variables de liaison à la date, et si vous êtes en mesure de transmettre une date nulle de type de données, elle traitera celle-ci comme prévu. Voir une illustration ci-dessous.

Certaines réponses, postées déjà, gèrent le problème secondaire - si vous passez dans NULL de type de données Char ou Varchar2, que se passe-t-il? Je ne pense pas comprendre que la raison précise est importante; Ce que est exceptionnellement important est de comprendre cette limitation des programmes frontaux, et - si vous êtes obligé de les utiliser pour interagir avec la base de données - assurez-vous que vos variables de liaison sont le type de données de chaîne et la requête reflète que (en utilisant TO_Date avec le modèle de format de date approprié).

Si vous utilisez pl / sql, et / ou peut-être d'autres environnements d'appel (pas sûr d'Apex par exemple, car je ne l'utilise pas ), vous CAN PASSEZ directement Type de données de date et obtenez le comportement attendu. Voici une illustration: Je construit votre requête comme une requête dynamique, avec des variables de liaison, et je l'appelle et transmettez-la nulle de type de données. Regardez ce qui se passe: xxx


0 commentaires

0
votes

Vous devez utiliser comme ci-dessous pour correspondre NULL avec NULL pour obtenir une ligne

select 1 from dual
where nvl('',SYSDATE) BETWEEN NVL('', SYSDATE) AND NVL('', SYSDATE)


1 commentaires

Cette réponse n'inclut pas la: start_date ou: fin_date



2
votes

Il y a des réponses intéressantes ici, mais je ne suis pas sûr que quelqu'un n'a pas encore expliqué pourquoi votre requête ne renvoie aucune ligne de lignes. (Toutes mes excuses s'ils l'ont et je l'ai manquée - ignorez-moi alors!)

C'est parce que nvl ('', sysdate) code> renvoie une chaîne de caractères forte>, car Le premier argument '' est un personnage STRNG. Donc, nvl ('', sysdate) code> est équivalent à nvl ('', to_char (sysdate)) code>. Et puisque nous n'avons pas spécifié le format de TO_CHAR, Oracle utilisera la valeur par défaut qui n'inclut généralement pas de composant temporel. p>

donc ceci: p> xxx pré>

est traité quelque chose comme ceci: p> xxx pré>

oracle sera alors Convertissez ces chaînes dans les dates pour effectuer les entre les deux, alors supposez 00:00:00 pour l'heure de la journée. Par conséquent, sauf si vous exécutez cela exactement à minuit, il ne retournera pas une ligne. P>

Toutefois, si vous définissez votre format de date par défaut pour inclure l'heure comme celle-ci: P>

select 1 from dual
where  SYSDATE BETWEEN NVL(TO_DATE(:START_DATE), SYSDATE)
                   AND NVL(TO_DATE(:END_DATE), SYSDATE)


0 commentaires