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 :

[High-Level] Gestion des nulls sans la fonction NVL [11g]


Sujet :

SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre régulier
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juin 2013
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 9
    Par défaut [High-Level] Gestion des nulls sans la fonction NVL
    Bonjour à tous,

    Dans le cadre de mon boulot, je suis amené à devoir comparer des attributs (jointure ou historisation SCD2) pouvant contenir la valeur null.

    Certaines requêtes pouvants être relativement volumineuses, on a rapidement écarté la solution d'inclure un "or is/not is null"

    Exemple (simple):

    Je dois comparer C1 et C2 et c'est 2 champs peuvent être nulls.

    ... Where C1 = C2 or (C1 is null and C2 is null)

    La seconde solution testée a été d'utiliser la fonction NVL qui permet de remplacer les nulls par une valeur afin d'effectuer des comparaisons.

    Le problème dans ce cas de figure c'est que la valeur de remplacement peut-elle être significative.

    Exemple :

    Numérique => NVL(C1,0) = NVL(C2,0)
    Caractère => NVL(C1, ' ') = NVL(C2,' ')

    Cependant le '0' ou le ' ' peuvent représenter quelque chose ce qui créé des conflits ou empêche de tenir compte de certains changements dans le cadre d'une historisation.

    Exemple :

    Si C1 (numérique) passe de null à 0, il est impossible de déterminer qu'il y a eu un changement car NVL(C1,0) ramène dans les 2 cas 0.

    La 3ème et dernières solution a été d'utiliser la fonction :

    DBMS_UTILITY.get_hash_value (C1, 1, POWER (2, 16) - 1)

    Cette fonction à la base prévue pour du cryptage, permet d'attribuer une valeur numérique à tout valeur rencontrée (y compris les nulls). Je pensais tenir-là la bonne solution mais j'ai vite déschanté lorsque je me suis rendu compte que lors de requêtes assez importantes (requêtes imbriquées, not exist,...) on arrivait avec un temps d'exécution irréaliste (pour les plus connaisseur on arrivait via un plan d'exécution à 41.000.000.000...).

    Je sais que ma question est relativement "high-level" mais j'espère quand-même que certains experts pourraient venir apporter leurs contributions...

    Merci d'avance

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 136
    Par défaut
    La solution avec NVL ne peut être utilisée qu'en spécifiant des valeurs non significatives en cas de NULL.
    Si toutes les valeurs acceptées par le type de la colonne à tester peuvent être significatives, seule la solution du OR..NULL est valide.
    Rien ne t’empêche de créer une fonction pour écrire cette comparaison de manière plus concise
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  3. #3
    Expert confirmé 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
    Par défaut
    La fonction non documentée SYS_OP_MAP_NONNULL permet ce type de comparaison. Mais, il est fortement déconseillé voir une folie d’utiliser des fonctions non-documentée dans un code pérenne.

  4. #4
    Membre régulier
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juin 2013
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 9
    Par défaut
    Citation Envoyé par mnitu Voir le message
    La fonction non documentée SYS_OP_MAP_NONNULL permet ce type de comparaison. Mais, il est fortement déconseillé voir une folie d’utiliser des fonctions non-documentée dans un code pérenne.
    Bonjour mnitu,

    Merci d'intervenir.
    Je me suis effectivement penché sur cette fonction qui semble à priori correspondre à mes attentes (en tout cas après quelques tests) mais malheureusement cette fonction n'étant pas "officielle" je ne peux me permettre de l'implémenter dans un cadre professionnel avec un risque qu'elle ne soit plus supportée dans une version future... ou alors ce serait faire passer la patate chaude au suivant...

  5. #5
    Membre régulier
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juin 2013
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 9
    Par défaut
    Citation Envoyé par al1_24 Voir le message
    La solution avec NVL ne peut être utilisée qu'en spécifiant des valeurs non significatives en cas de NULL.
    Si toutes les valeurs acceptées par le type de la colonne à tester peuvent être significatives, seule la solution du OR..NULL est valide.
    Rien ne t’empêche de créer une fonction pour écrire cette comparaison de manière plus concise
    Bonjour al1_24,

    Avant tout, merci pour ta réactivité.

    Une telle fonction serait réalisable mais le fait de repasser par une fonction n'est-ce pas problematique ? Je pensais en effet que le problème de la fonction "get_hash_value" et de sa lenteur était justement lié à l'appel systématique d'une fonction qui ne travaille pas en mémoire. En d'autres mots, je pensais que lors d'une jointure entre des tables de plusieurs millions de records, oracle effectuait un appel à cette fonction à chaque comparaison ce qui provoquait un délai de traitement énorme. Contrairement (si mes souvenirs sont bons) au NVL qui lui traitait ça en mémoire.

    Ne vais-je pas rencontrer ce même problème si je passe par une fonction sql autre que celles fournies par défaut ?

  6. #6
    Membre confirmé
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juin 2013
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2013
    Messages : 19
    Par défaut
    Bonjour,

    Comme al1_24 l'a dit :

    Citation Envoyé par al1_24 Voir le message
    La solution avec NVL ne peut être utilisée qu'en spécifiant des valeurs non significatives en cas de NULL.
    Si toutes les valeurs acceptées par le type de la colonne à tester peuvent être significatives, seule la solution du OR..NULL est valide.
    Rien ne t’empêche de créer une fonction pour écrire cette comparaison de manière plus concise
    J'ajouterai que dans l'exemple que tu as fournit apparemment les valeurs des deux colonnes sont toujours positives, pourquoi ne pas utiliser une valeur négative ?

    Autre point, pour des questions de lenteurs, tu peux créer des index sur des fonctions.
    exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    create index emp_null_sal on emp (nvl(sal,0));

  7. #7
    Membre régulier
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juin 2013
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 9
    Par défaut
    Citation Envoyé par doubleDu Voir le message
    Bonjour,

    Comme al1_24 l'a dit :



    J'ajouterai que dans l'exemple que tu as fournit apparemment les valeurs des deux colonnes sont toujours positives, pourquoi ne pas utiliser une valeur négative ?

    Autre point, pour des questions de lenteurs, tu peux créer des index sur des fonctions.
    exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    create index emp_null_sal on emp (nvl(sal,0));
    Bonjour doubleDu,

    Je travaille pour une assurance et les attributs numériques peuvent dans certains cas représenter des montants qui peuvent être positifs ou négatifs (prime ou prestation)

    Les index, eux, sont malheureusement déjà bien en place...

  8. #8
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 136
    Par défaut
    Citation Envoyé par Beluz Voir le message
    Je travaille pour une assurance et les attributs numériques peuvent dans certains cas représenter des montants qui peuvent être positifs ou négatifs (prime ou prestation)
    Est-ce que les valeurs extrêmes de ces colonnes numériques sont souvent utilisées ?
    Par exemple -9999 sur un NUMBER(4, 0)
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  9. #9
    Membre régulier
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juin 2013
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 9
    Par défaut
    Il y a toujours un risque vu que cela peut représenter un montant mais je dois avouer que c'est effectivement ma roue de secours, la moins mauvaise des solutions...
    Utiliser des valeurs extrêmes numériques et des caractère "spéciaux" (voir si compatibilité des différents code ASCII au niveau des DB) pour essayer de réduire au maximum le risque de conflit.

  10. #10
    Membre Expert

    Homme Profil pro
    Inscrit en
    Mars 2010
    Messages
    536
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 536
    Par défaut
    Je ne sais pas si j'ai bien compris votre besoin mais j'opterai (avec précaution car je n'ai pas trop bien saisi votre demande) à quelque chose comme ceci

    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
     
    SQL> select * from emp where
      2  comm = sal;
     
         EMPNO ENAME      JOB              MGR HIREDATE                 SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
          7369 allen      clerk           7902 20100330 00:00:00         25         25         20
     
    SQL>
    SQL> select * from emp where
      2  comm is null;
     
         EMPNO ENAME      JOB              MGR HIREDATE                 SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
             3 Mohamed    Oracle          7654 20120808 15:05:19        500                    20
     
    SQL>
    SQL> select * from emp where
      2  sal is null;
     
         EMPNO ENAME      JOB              MGR HIREDATE                 SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
          7788 scott      analyst         7566 19821209 00:00:00                     5         20
     
    SQL> select * from emp where lnnvl(comm != sal);
     
         EMPNO ENAME      JOB              MGR HIREDATE                 SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
          7369 allen      clerk           7902 20100330 00:00:00         25         25         20
          7788 scott      analyst         7566 19821209 00:00:00                     5         20
             3 Mohamed    Oracle          7654 20120808 15:05:19        500                    20

  11. #11
    Membre régulier
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juin 2013
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 9
    Par défaut
    Citation Envoyé par Mohamed.Houri Voir le message
    Je ne sais pas si j'ai bien compris votre besoin mais j'opterai (avec précaution car je n'ai pas trop bien saisi votre demande) à quelque chose comme ceci

    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
     
    SQL> select * from emp where
      2  comm = sal;
     
         EMPNO ENAME      JOB              MGR HIREDATE                 SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
          7369 allen      clerk           7902 20100330 00:00:00         25         25         20
     
    SQL>
    SQL> select * from emp where
      2  comm is null;
     
         EMPNO ENAME      JOB              MGR HIREDATE                 SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
             3 Mohamed    Oracle          7654 20120808 15:05:19        500                    20
     
    SQL>
    SQL> select * from emp where
      2  sal is null;
     
         EMPNO ENAME      JOB              MGR HIREDATE                 SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
          7788 scott      analyst         7566 19821209 00:00:00                     5         20
     
    SQL> select * from emp where lnnvl(comm != sal);
     
         EMPNO ENAME      JOB              MGR HIREDATE                 SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
          7369 allen      clerk           7902 20100330 00:00:00         25         25         20
          7788 scott      analyst         7566 19821209 00:00:00                     5         20
             3 Mohamed    Oracle          7654 20120808 15:05:19        500                    20
    Bonjour Mohamed.Houri,

    la fonction LNNVL renvoi une condition inversée, en résumé :

    TRUE => FALSE
    FALSE => TRUE
    UNKNOWN => TRUE

    Du coup si on suis cette logique,

    Si on compare 'A' avec 'A' il nous retourne FALSE

    Si on compare 'A' avec 'B' il nous retourne TRUE

    Si on compare null avec null il nous retourne TRUE

    Mais du coup, il impossible de distinguer lors d'une historisation un cas de figure ou la comparaison est différente ou bien si il compare 2x la valeur null (qui elle ne nécessite pas d'intervention car les valeurs n'ont pas changées...)


  12. #12
    Membre régulier
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juin 2013
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 9
    Par défaut
    Ah désolé, c'est vrai que dans l'exemple, tu n'utilise pas une égalité mais un "différent"... ça demande réflexion du coup...

  13. #13
    Membre régulier
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juin 2013
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2013
    Messages : 9
    Par défaut
    Citation Envoyé par Beluz Voir le message
    Bonjour Mohamed.Houri,

    la fonction LNNVL renvoi une condition inversée, en résumé :

    TRUE => FALSE
    FALSE => TRUE
    UNKNOWN => TRUE

    Du coup si on suis cette logique,

    Si on compare 'A' avec 'A' il nous retourne FALSE

    Si on compare 'A' avec 'B' il nous retourne TRUE

    Si on compare null avec null il nous retourne TRUE

    Mais du coup, il impossible de distinguer lors d'une historisation un cas de figure ou la comparaison est différente ou bien si il compare 2x la valeur null (qui elle ne nécessite pas d'intervention car les valeurs n'ont pas changées...)


    Après réflexion, cette solution ne sera pas bonne car il est impossible de distinguer une comparaison de type :

    A = null (qui retourne la valeur correpsondant à inconnu)
    à
    null = null (qui retourne la valeur correpsondant à inconnu)

    Cependant dans le premier cas de figure il y a une modification qui nécessite une historisation mais pas dans le 2ème...

    Quelqu'un aurait-il une corde sous la main ??

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Export au format txt : gestion des NULL
    Par guidav dans le forum Access
    Réponses: 3
    Dernier message: 08/08/2006, 11h28
  2. [VB2005] Gestion des évenement dans une fonction
    Par arnolem dans le forum Windows Forms
    Réponses: 8
    Dernier message: 24/07/2006, 09h07
  3. Gestion des NULL dans les tables externes
    Par plouf2244 dans le forum Firebird
    Réponses: 1
    Dernier message: 23/03/2006, 16h55
  4. Gestion des buffers dans une fonction
    Par JiJiJaco dans le forum Langage
    Réponses: 2
    Dernier message: 06/01/2006, 11h20
  5. Gestion des null
    Par Bruno75 dans le forum Décisions SGBD
    Réponses: 19
    Dernier message: 20/09/2004, 13h34

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