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

Oracle Discussion :

[9i] 'aa' = 'aa ' ?


Sujet :

Oracle

  1. #1
    Membre émérite Avatar de nuke_y
    Profil pro
    Indépendant en analyse de données
    Inscrit en
    Mai 2004
    Messages
    2 076
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Indépendant en analyse de données

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 076
    Points : 2 370
    Points
    2 370
    Par défaut [9i] 'aa' = 'aa ' ?
    Bonjour,

    que renvoie ceci chez vous ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select 1 from DUAL where 'aa' = 'aa    ';
    Et vous trouvez ça normal? Parce que moi... conceptuellement ça me gène... Surtout que ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select 1 from DUAL where 'aa' like 'aa    ';
    ne me renvoie aucune ligne.

    Est-ce normal ? (En attendant vos réponses je vais commencer à m'ouvrir les veines, avec le temps que ça prend à se vider faut que je m'y prenne dès maintenant si je veux en avoir finit avant ce soir)

  2. #2
    Membre confirmé
    Inscrit en
    Décembre 2003
    Messages
    493
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 493
    Points : 605
    Points
    605
    Par défaut
    tout cela pour nous dire quoi ?

  3. #3
    Membre émérite Avatar de nuke_y
    Profil pro
    Indépendant en analyse de données
    Inscrit en
    Mai 2004
    Messages
    2 076
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Indépendant en analyse de données

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 076
    Points : 2 370
    Points
    2 370
    Par défaut
    Que (sous SQL*Plus en tous cas) l'égalité entre 2 constantes String dont une est terminée par des espaces alors que l'autre non est VRAIE !! Et que personnellement je trouve cela complétement dingue !! Alors j'aimerais savoir si c'est normal, et pourquoi ? Est-ce que ça dépend des versions ? Je trouve ça assez grave que l'opérateur = prenne la liberté d'enlever les espaces de la fin...

  4. #4
    Membre à l'essai
    Inscrit en
    Août 2004
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 27
    Points : 11
    Points
    11
    Par défaut
    vaudrait pi etre mieu faire un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select 1 from DUAL where 'aa' like 'aa%';
    Mais c'est vrai que c'est étonnant que le = vire les espaces..

  5. #5
    Membre émérite Avatar de nuke_y
    Profil pro
    Indépendant en analyse de données
    Inscrit en
    Mai 2004
    Messages
    2 076
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Indépendant en analyse de données

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 076
    Points : 2 370
    Points
    2 370
    Par défaut
    Ah mais attention ! Avec LIKE ça roule, ça c'est sûr. Et l'opérateur "=" renvoie bien FAUX si on fait la comparaison entre 2 champs ou entre 1 champ et une constante. Par contre, si on fait la comparaison entre 2 constantes (je sais ça ne sert à rien) il ignore les espaces en fin de chaîne !!
    Le problème se pose chez nous car nous organisons une migration de SQLServer vers Oracle et que l'opérateur "=" de SQLServer ignore AUSSI les espaces en fin de chaîne si on compare un champ et une constante.

    En gros si j'ai une table test contenant une ligne et le champ chp_test dans ma table test qui contient la valeur 'test' :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Select 1 from test where chp_test = 'test'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Select 1 from test where chp_test = 'test   '
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Select 1 from test where 'test'= 'test   '
    les requêtes renvoient toutes les 3 une ligne (avec la valeur 1) sous SQLServer alors que sous Oracle seules la 1ere et la dernière le font. La 2e ne renvoit rien. D'où une DIFFERENCE FONCTIONNELLE majeure qui a filtré lors de l'analyse et de gros gros problèmes maintenant puisque on ne sait pas combien de champs sont touchés par ce problème.

    D'où... ben gloups !
    [/code]

  6. #6
    Rédacteur

    Homme Profil pro
    Consultant / formateur Oracle et SQL Server
    Inscrit en
    Décembre 2002
    Messages
    3 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Consultant / formateur Oracle et SQL Server

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 461
    Points : 8 079
    Points
    8 079
    Par défaut
    Je ne connaissais pas non plus cette particularité, que je constate aussi en testant.
    Mais comme vous dites, tester l'égalité de 2 constantes est d'un intérêt limité.

    Attention toutefois à ne pas conclure d'un test unique que SQL Server (ou Oracle) fonctionne de telle ou telle manière.
    Le comportement observé dépend souvent d'un paramétrage particulier, éventuellement par défaut, mais qui peut être modifiable.

    Par exemple, sous Oracle, si vous choisissez un type CHAR et non VARCHAR2, 'toto' et 'toto ' (avec autant d'espaces finaux que vous voulez) sont considérés comme égaux.

  7. #7
    Membre émérite Avatar de nuke_y
    Profil pro
    Indépendant en analyse de données
    Inscrit en
    Mai 2004
    Messages
    2 076
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Indépendant en analyse de données

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 076
    Points : 2 370
    Points
    2 370
    Par défaut
    Voui je me suis un peu emporté, disons que c'est une grosse catastrophe pour nous mais que comme on l'a déjà dit, ça ne touche que la comparaison de 2 constantes. Donc il doit être assez rare que ça puisse géner la majorité des utilisateurs d'Oracle (quoiqu'il n'est pas rare que des requêtes générées par des outils de reporting contiennent des comparaison entre constantes, pour des histoires louches de contrôles de saisie utilisateur).

    Le but de ce post en fait, était plus d'informer les gens de cette différence là, histoire que d'autres personnes n'ait pas le même problème.

    Pour nous je pense que c'est mort puisque la 1/2 de nos données ont des espaces à la fin, que ce soit sous SQLServer ou sous Oracle (et pas au même endroit, pour faire simple !!). L'analyse est pourrie, nous devons donc ré-analyser rapidement, appliquer les corrections sur les procédures d'importation et sur les tables touchées (sans compter qu'il faut les trouver). Enfin bref, le genre de problème désagréable à découvrir en fin de projet, au moment où on greffe les outils de reporting sur la base ...

  8. #8
    Membre averti

    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    379
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 379
    Points : 376
    Points
    376
    Par défaut
    il ne faut jamais oublier que ' ' est différent de '' et cela dans la plus part des language.

    pour éviter cela, il existe une fonction trim() pour supprimer les espaces devant et derrière la chaîne.

    le test devient alors:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select 1 from DUAL where 'aa' = trim('aa    ');
    ou dans ce cas précis:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select 1 from DUAL where 'aa' = rtrim('aa    ');
    et cela fonctionnera correctement.

    pour localiser les enregistrements pourris:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select * from matable where nonchamp != trim( monchamp );
    simple rapide efficace.

    une autre solution et comme expliqué, est d'utiliser des champs de type "char" qui eux complète automatiquement la chaîne avec des espaces, espaces qui seront retournés d'office dans vos résultats, ainsi gare à la surprise:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select champ1 || champ2 from matable;
    qui risque de retourner "machin bidulle" alors que vous attendez "machinbidulle"

    encore une fois, un trim ou rtrim (juste sur la droite) réglera le problème.

  9. #9
    Membre émérite Avatar de nuke_y
    Profil pro
    Indépendant en analyse de données
    Inscrit en
    Mai 2004
    Messages
    2 076
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Indépendant en analyse de données

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 076
    Points : 2 370
    Points
    2 370
    Par défaut
    Euh ... disons que pour " et ' ils n'ont pas du tout la même utilisation dans la plupart des languages surtout, donc ça ne règle pas mon problème.

    Comme je l'ai déjà dit, il n'y a pas de solution simple à mon problème (250 tables, 150 Go de données, même en passant un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    blabla where monchamp like '% '
    , il me faudra des heures pour tout corriger), il va falloir ré-analyser, modifier les procédures d'importation, etc. Et TOUT retester !!
    J'ai juste ouvert ce sujet pour informer les gens que ce problème existe, de cette différence entre SQLServer et Oracle et pour qu'une autre personne ne commette pas la même erreur que notre analyste qui s'est basé sur un test entre 2 constantes pour valider le comportement entre Oracle et SQLServer.

    Quant aux char c'est une bonne idée, mais uniquement pour les champs de faible longueur (ce qui aurait été le cas ici) qui servent de clés. Malheureusement il est vraiment trop tard pour reprendre la structure de la base de manière aussi importante.

  10. #10
    Membre expérimenté

    Profil pro
    Inscrit en
    Mai 2003
    Messages
    412
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2003
    Messages : 412
    Points : 1 326
    Points
    1 326
    Par défaut
    Pour info

    La prochaine fois tu pourras utiliser ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT 1
    FROM dual
    WHERE dump('test')=dump('test            ');
    Pour ce qui est de ce problème je continue les recherches (je pense que c'est du à un bug car cela me parait bizarre = fait un test boolean donc les chaines doivent absolument etre identique)

  11. #11
    Membre émérite Avatar de nuke_y
    Profil pro
    Indépendant en analyse de données
    Inscrit en
    Mai 2004
    Messages
    2 076
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Indépendant en analyse de données

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 076
    Points : 2 370
    Points
    2 370
    Par défaut
    Merci pour cette fonction, je ne connaissais pas.

    J'attends des news pour savoir si c'est un bug ou pas. Je suis de ton avis, pour moi un "=" c'est un "=" !! M'enfin le PIRE c'est SQLServer qui ignore les espaces même entre un champ et une constante !

  12. #12
    Rédacteur

    Inscrit en
    Septembre 2004
    Messages
    626
    Détails du profil
    Informations forums :
    Inscription : Septembre 2004
    Messages : 626
    Points : 848
    Points
    848
    Par défaut
    J'ai l'impression qu'Oracle considère par défaut les constantes de chaines de caractères comme des CHAR :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SQL> create table TEST as select 'blabla' x, 'blabla   ' y from dual;
     
    Table created.
     
    SQL> desc TEST
     Name                                      Null?    Type
     ----------------------------------------- -------- ----------------------------
     X                                                  CHAR(6)
     Y                                                  CHAR(9)
    Et :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    SQL> select 1
      2  from   dual
      3  where  cast('blabla' as varchar2(20)) = cast('blabla   ' as varchar2(20));
     
    no rows selected
     
    SQL> select 1
      2  from   dual
      3  where  cast('blabla' as char(20)) = cast('blabla   ' as char(20));
     
             1
    ----------
             1
    Ceci explique cela pour moi.


    Laly.

  13. #13
    Futur Membre du Club
    Inscrit en
    Mars 2005
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 7
    Points : 6
    Points
    6
    Par défaut
    Bonjour à tous,
    en fait j'ai essayé sur SQL Navigator 4.3
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select 1 from DUAL where 'aa' = 'aa    ';
    qui a donné le meme resultat que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select 1 from DUAL where 'aa' like 'aa    ';
    par contre cette cmde
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT 1 
    FROM dual 
    WHERE dump('test')=dump('test            ');
    n'a pas marché???? [/code]

  14. #14
    Membre émérite Avatar de nuke_y
    Profil pro
    Indépendant en analyse de données
    Inscrit en
    Mai 2004
    Messages
    2 076
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Indépendant en analyse de données

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 076
    Points : 2 370
    Points
    2 370
    Par défaut
    Ok !!!!
    Ben voila CA c'est une explication, et une bonne. Merci Lalystar. Je met un tag résolu donc, et on aura appris quelquechose aujourd'hui.

  15. #15
    Rédacteur

    Inscrit en
    Septembre 2004
    Messages
    626
    Détails du profil
    Informations forums :
    Inscription : Septembre 2004
    Messages : 626
    Points : 848
    Points
    848
    Par défaut
    Le mérite en revient à Pomalaix en fait, je ne savais pas qu'avec des CHAR 'blabla ' = 'blabla'.


    Laly.

  16. #16
    Membre expert
    Avatar de bouyao
    Inscrit en
    Janvier 2005
    Messages
    1 778
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 778
    Points : 3 033
    Points
    3 033
    Par défaut
    Voici un autre exemple :
    SQL>variable a char(7)
    SQL>variable b varchar2(7)
    SQL>exec :a := 'aa '
    SQL>exec :b : ='aa'
    SQL>select 1 from dual where 'aa'=:a;
    1
    ----------
    1
    SQL>select 1 from dual where 'aa'=:b;
    aucune ligne selectionnée

  17. #17
    Membre émérite Avatar de nuke_y
    Profil pro
    Indépendant en analyse de données
    Inscrit en
    Mai 2004
    Messages
    2 076
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Indépendant en analyse de données

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 076
    Points : 2 370
    Points
    2 370
    Par défaut
    Bah bravo à tous alors, même à ceux que j'oublie !

  18. #18
    Rédacteur

    Homme Profil pro
    Consultant / formateur Oracle et SQL Server
    Inscrit en
    Décembre 2002
    Messages
    3 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Consultant / formateur Oracle et SQL Server

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 461
    Points : 8 079
    Points
    8 079
    Par défaut
    Comme il fallait s'y attendre, ce comportement est parfaitement documenté :
    http://download-west.oracle.com/docs...ts2a.htm#45443, et plus précisément la rubrique "Datatype Comparison Rules".

    Que celui qui avait déjà lu ça se présente pour recevoir sa médaille en chocolat !


    On y lit que Oracle uses blank-padded comparison semantics only when both values in the comparison are either expressions of datatype CHAR, NCHAR, text literals, or values returned by the USER function.

    En clair, les espaces terminaux sont ignorés lors de la comparaison de valeurs de type CHAR, NCHAR ou de valeurs textuelles "en dur".

  19. #19
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 075
    Points
    19 075
    Par défaut
    fallait trouver

    c'est beau les couleurs

  20. #20
    Membre émérite Avatar de nuke_y
    Profil pro
    Indépendant en analyse de données
    Inscrit en
    Mai 2004
    Messages
    2 076
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Indépendant en analyse de données

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 076
    Points : 2 370
    Points
    2 370
    Par défaut
    Je suis content d'avoir permis à tous de connaître ce comportement si euh CATASTROPHIQUE pour nous

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

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