IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SQL Oracle Discussion :

NULL n'est pas égal à NULL et aucune ligne en résultat


Sujet :

SQL Oracle

  1. #1
    Expert éminent
    Avatar de elitost
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2003
    Messages
    1 985
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 985
    Points : 6 566
    Points
    6 566
    Par défaut NULL n'est pas égal à NULL et aucune ligne en résultat
    Bonjour,

    J'ai une table avec une colonne de type date.

    Cette table a été initialisée avec des données.

    Dans une procédure stockée, on passe un paramètre de type date pour l'utiliser dans une requête dans le code de la procédure stockée.

    La requête est la suivante (volontairement tronquée) :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT *
    FROM matable
    WHERE coldate = nvl(:parametredate,coldate)

    Nous utilisons la fonction NVL pour gérer les cas ou le paramètre de type date de la procédure n'est pas valorisé, donc passé avec la valeur NULL.

    Le problème maintenant c'est que NULL n'est pas égal à NULL et dans le cas du paramètre date envoyé à NULL, la requête ne retourne aucun résultat.

    Une idée pour palier à ce problème ?

    Merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Points : 11 862
    Points
    11 862
    Par défaut
    Qui vous dit que coldate n'est pas NULL également ?
    Rédacteur Oracle (Oracle ACE)
    Guide Oracle ,Guide PL/SQL, Guide Forms 9i/10g, Index de recherche
    Je ne réponds pas aux questions techniques par MP
    Blogs: Forms-PL/SQL-J2EE - Forms Java Beans

  3. #3
    Expert éminent
    Avatar de elitost
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2003
    Messages
    1 985
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 985
    Points : 6 566
    Points
    6 566
    Par défaut
    Citation Envoyé par SheikYerbouti Voir le message
    Qui vous dit que coldate n'est pas NULL également ?
    Effectivement je me suis mal expliqué (après relecture), le problème se pose pour les enregistrements pour lesquels la colonne coldate est valorisée à NULL, je souhaiterais que ma requête SQL me renvoie ces enregistrements.

    J'ai bien pensé à tester la nullité du paramètre avant de construire la requête mais je me demandais si il n'y avait pas une autre solution ?

  4. #4
    Expert éminent sénior
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Points : 11 862
    Points
    11 862
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT *
    FROM matable
    WHERE coldate IS NULL;
    Rédacteur Oracle (Oracle ACE)
    Guide Oracle ,Guide PL/SQL, Guide Forms 9i/10g, Index de recherche
    Je ne réponds pas aux questions techniques par MP
    Blogs: Forms-PL/SQL-J2EE - Forms Java Beans

  5. #5
    Expert éminent
    Avatar de elitost
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2003
    Messages
    1 985
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 985
    Points : 6 566
    Points
    6 566
    Par défaut
    Citation Envoyé par SheikYerbouti Voir le message
    SELECT *
    FROM matable
    WHERE coldate IS NULL
    En fait non, en une seule requête je voudrais gérer les cas :
    - Le paramètre date est NULL
    - Le paramètre date est autre que NULL
    - La colonne coldate est à NULL
    - La colonne coldate est à autre que NULL

    Pour le moment avec ma requête actuelle :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT *
    FROM matable
    WHERE coldate = nvl(:parametredate,coldate)

    Si matable contient les données suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    coldate
    12/08/2007
    NULL
    NULL
    15/09/2005
    En passant 15/09/2005 en paramètre, j'obtiens la ligne correspondante (la 4ème).
    En passant NULL en paramètre, je n'obtiens aucun résultat.

    C'est normal car ma requête revient à faire dans le cas d'un paramètre à NULL :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT *
    FROM matable
    WHERE NULL = NULL

    Je souhaiterais donc pouvoir gérer tous les cas en un seule requête, est ce possible ?

  6. #6
    Membre actif Avatar de DAB.cz
    Inscrit en
    Octobre 2006
    Messages
    221
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 221
    Points : 249
    Points
    249
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT *
    FROM matable
    WHERE (coldate is null and :parametredate is null) or (coldate = :parametredate)

  7. #7
    Expert éminent
    Avatar de elitost
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2003
    Messages
    1 985
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 985
    Points : 6 566
    Points
    6 566
    Par défaut
    J'essaierai demain.

    Cette solution est elle très pénalisant pour le temps de réponse ?

  8. #8
    Membre actif Avatar de DAB.cz
    Inscrit en
    Octobre 2006
    Messages
    221
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 221
    Points : 249
    Points
    249
    Par défaut
    Citation Envoyé par elitost Voir le message
    Cette solution est elle très pénalisant pour le temps de réponse ?
    Oui, l'index sur coldate ne sera pas utilisé (existe-t-il?) pour la condition "IS NULL", alors: FULL SCAN.

  9. #9
    Expert éminent
    Avatar de elitost
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2003
    Messages
    1 985
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 985
    Points : 6 566
    Points
    6 566
    Par défaut
    C'est donc peut être mieux de construire le select dynamiquement (Si param data pas NULL alors ajouter le filtre au select Fin Si) et dans le cas du paramètre valorisé à NULL d'avoir uniquement la requête :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    select * from matable

    A moins qu'il y ai d'autres solutions pour arriver à solutionner le souci de cette requête ?

  10. #10
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Points : 4 926
    Points
    4 926
    Par défaut
    Citation Envoyé par DAB.cz Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT *
    FROM matable
    WHERE (coldate is null and :parametredate is null) or (coldate = :parametredate)
    c'est à mon sens la solution la plus élégante !


    quand à la performance, on peut imaginer (ce n'est pas le goût de tout le monde) de te pas avoir de null dans la table, mais une date du style 31-DEC-9999. Cela résout le problème de performance.

  11. #11
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Points : 4 926
    Points
    4 926
    Par défaut
    une autre approche serait d'indexer les nulls et d'utiliser UNION ALL
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SQL> var parametredate number
    SQL> create table matable(coldate number, x number);
    Table created.
    SQL> insert into matable 
         select nullif(rownum,1),1 from all_objects where rownum<100;
    99 rows created.
    SQL> create index i on matable(coldate,1) compute statistics;
    Index created.
    SQL> analyze table matable compute statistics;
    Table analyzed.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    select *  FROM matable  WHERE coldate is null and :parametredate is null
    union all
    select * FROM matable WHERE coldate = :parametredate;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    ------------------------------------------------------------------------------
    | Id  | Operation                     | Name    | Rows  | Bytes | Cost (%CPU)|
    ------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT              |         |     2 |     8 |     4  (50)| 
    |   1 |  UNION-ALL                    |         |       |       |            |
    |*  2 |   FILTER                      |         |       |       |            |
    |   3 |    TABLE ACCESS BY INDEX ROWID| MATABLE |     1 |     4 |     2   (0)|
    |*  4 |     INDEX RANGE SCAN          | I       |     1 |       |     1   (0)| 
    |   5 |   TABLE ACCESS BY INDEX ROWID | MATABLE |     1 |     4 |     2   (0)|
    |*  6 |    INDEX RANGE SCAN           | I       |     1 |       |     1   (0)|
    ------------------------------------------------------------------------------
       2 - filter(:PARAMETREDATE IS NULL)
       4 - access("COLDATE" IS NULL)
       6 - access("COLDATE"=TO_NUMBER(:PARAMETREDATE))
    ou bien sûr de créer 2 selects différents, un pour les null, un pour les non-null

  12. #12
    Expert éminent
    Avatar de elitost
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2003
    Messages
    1 985
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 985
    Points : 6 566
    Points
    6 566
    Par défaut
    Ok, je vous remercie pour toutes ces informations qui devraient maintenant suffire pour choisir telle ou telle solution.

    Merci encore et bonne journée à tous.

  13. #13
    Membre actif Avatar de DAB.cz
    Inscrit en
    Octobre 2006
    Messages
    221
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 221
    Points : 249
    Points
    249
    Par défaut
    Citation Envoyé par laurentschneider Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    create index i on matable(coldate,1)
    indexer les nulls, l'idée formidable et utile

  14. #14
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    SQL> create bitmap index b_i on matable (coldate)
      2  /
     
    Index crÚÚ.
     
    SQL>
    SQL> analyze table matable compute statistics;
     
    Table analysÚe.
     
    SQL> /
     
    Table analysÚe.
     
    SQL>
    SQL> SELECT *
      2  FROM matable
      3  WHERE (coldate IS NULL AND :parametredate IS NULL) OR (coldate = :parametredate)
      4  /
     
    Plan d'exÚcution
    ----------------------------------------------------------
    Plan hash value: 2725285456
     
    ----------------------------------------------------------------------------------------
    | Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT             |         |     1 |     4 |     3   (0)| 00:00:01 |
    |*  1 |  TABLE ACCESS BY INDEX ROWID | MATABLE |     1 |     4 |     3   (0)| 00:00:01 |
    |   2 |   BITMAP CONVERSION TO ROWIDS|         |       |       |            |          |
    |   3 |    BITMAP OR                 |         |       |       |            |          |
    |*  4 |     BITMAP INDEX SINGLE VALUE| B_I     |       |       |            |          |
    |*  5 |     BITMAP INDEX SINGLE VALUE| B_I     |       |       |            |          |
    ----------------------------------------------------------------------------------------
    Mais ça peut côuter cher.

  15. #15
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Points : 4 926
    Points
    4 926
    Par défaut
    bitmap index sur une date? mauvais plan

  16. #16
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Citation Envoyé par laurentschneider Voir le message
    bitmap index sur une date? mauvais plan
    Peut tu expliquer, STP ?

  17. #17
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Points : 4 926
    Points
    4 926
    Par défaut
    ben en general une date est une colonne a forte cardinalite, non?

    Bon c'est vrai que si c'est CONTRACT_END_DATE et que les contrats se terminent tous au 31 decembre on pourrait l'imaginer.

  18. #18
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    D’accorde Laurent, j’ai eu peur que c’était une hérésie même de penser à faire un bitmap index sur une colonne de type date.

    A propos,
    ...
    (ce n'est pas le goût de tout le monde) de te pas avoir de null dans la table, mais une date du style 31-DEC-9999. Cela résout le problème de performance.
    j’ai lu quelque part que ce n’est pas forcement une affaire de goût mais que ça pourrait être un problème de performance d’utiliser cette solution. Puis-je avoir ton point de vue sur ce sujet ?

  19. #19
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Points : 4 926
    Points
    4 926
    Par défaut
    si tu as beaucoup de NULLs, il n'est peut-etre pas necessaire de les indexer, vu qu'un WHERE X IS NULL te retournera une bonne partie de la table. Cependant si tu utilises des requetes du style WHERE D > SYSDATE OR D IS NULL, alors de remplacer NULL par 9999-12-31 sera benefique.

    C'est vrai que d'avoir des valeurs artificielles comme 9999-12-31 c'est pas terrible d'un pont de vue design

  20. #20
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Merci Laurent pour ta patience.

    En fin de compte y a-t-il une différence entre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    CREATE INDEX i ON matable(coldate,1)
    Et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    CREATE INDEX i ON matable(Nvl(coldate,1))
    Ne pense tu pas que c’est plus clair d’utiliser NVL ?

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Sum(Null()) n est pas null
    Par CLEM_BUGTRACK dans le forum QlikView
    Réponses: 2
    Dernier message: 07/05/2015, 16h00
  2. [PDO] Les requete PDO ne prennent pas en compte la premier ligne de résultat
    Par -Fly- dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 28/03/2012, 21h59
  3. syntaxe de n'est pas égal en code
    Par froutloops62 dans le forum Access
    Réponses: 3
    Dernier message: 12/07/2007, 23h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo