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 :

espace en fin des valeurs de recherche dans les jointures


Sujet :

Oracle

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Ao�t 2004
    Messages
    30
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 30
    Par d�faut espace en fin des valeurs de recherche dans les jointures
    Bonjour,

    Oracle 9.2.0
    Soit une table et une valeur :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    create table ma_table (col varchar2(5));
    insert into ma_table values ('toto');
    et 2 requetes :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    select * from ma_table where col = 'toto'
    qui marche.
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    select * from ma_table where col = 'toto '
    <= avec un espace !
    qui ne marche pas evidemment avec une configuration Oracle par defaut.

    Existe t'il un mecanisme ou un parametrage de la base qui permettrait de faire fonctionner ma seconde requete de facon transparente pour elle ?

    J'ai lu ce qu'explique SQLPro concernant les collations, je me disais que ce mecanisme pourrais peut etre etre une solution

    Merci,
    JR

  2. #2
    Expert confirm�
    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
    Par d�faut
    select * from ma_table where col LIKE 'toto%'

    ou

    select * from ma_table where TRIM(col) = 'toto'

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Ao�t 2004
    Messages
    30
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 30
    Par d�faut
    Oui si je modifie ma requete j'ai plein de solution.
    Je connais le sql, moins le fichier init.ora
    Y a t il un moyen de faire fonctionner ma requete sans la changer via une configuration particuliere de mon instance ?

    Merci,
    JR

  4. #4
    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
    Par d�faut
    Bonjour

    Merci de penser � utiliser les balises adapt�es pour formater votre code, conform�ment � la tradition du forum !

    Je vois 3 solutions pour r�soudre votre probl�me.

    1) Nettoyer les donn�es en amont.
    Est-il normal que vous ayez des espaces dans vos donn�es ?
    Si c'est non, alors il faudrait �liminer les espaces lors de l'insertion ou de la modification des donn�es, gr�ce � un d�clencheur par exemple.
    Pour les donn�es existantes, les fonctions TRIM/RTRIM/LTRIM vous seront utiles.

    2) Utiliser des CHAR au lieu des VARCHAR2.
    Cette solution convient id�alement � des cha�nes qui n'auraient des espaces qu'� droite, et qui seraient toutes plus ou moins de la m�me longueur (pour ne pas perdre trop d'espace).
    En effet, dans un CHAR, les espaces de droite sont ignor�s quand on fait un WHERE =.
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    CREATE TABLE TEST(a CHAR(10));
    INSERT INTO TEST VALUES('toto');
    INSERT INTO TEST VALUES('toto ');
     
    SELECT * FROM TEST WHERE a='toto';
    --> 
    toto
    toto
    3) Si les espaces doivent �tre conserv�s (et que vous �tes au moins en 8i), vous pouvez cr�er un index fonctionnel sur la colonne VARCHAR2.
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    CREATE INDEX F_RTRIM ON TEST(rtrim(a));
    Ensuite, la recherche ne se fait plus par
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    SELECT * FROM TEST WHERE a='toto';
    mais par
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    SELECT * FROM TEST WHERE rtrim(a)='toto';
    L'avantage de l'index fonctionnel, c'est que cette recherche sera aussi rapide que si la donn�e avait �t� stock�e sans les espaces.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Ao�t 2004
    Messages
    30
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 30
    Par d�faut
    J'ai corrige mon post

    L'index fonctionnel me semble tres interessant dans la mesure ou d'apres les ecrits de SQLPro le mecanisme de collation est tres couteux, cela dit je crois qu'il ne pourrait pas repondre a mon probleme

    Ces espaces proviennent du Pro*C.
    Les valeurs sont recuperes dans des types char UNIX.
    Migrer ces types vers du varchar + rajouter la gestion du \0 de fin de chaine serait trop de travail.
    Donc les chaines ne seront pas nettoyees, a priori ..., (bien que le surplus d'espace occupe par la transmission de ces espaces risque de s'averer embettant et que cette position sera peut etre revue).

    Donc l'index pourrait repondre a mon besoin.
    J'ai une question qui me vient suite a cela ...

    J'ai essaye de faire moi meme le test mais je n'ai pas assez de privilege. . Cela me surprend que je ne puisse pas creer un index sur une colonne d'une table m'appartenent mais bon admettons

    Est ce que la mise a jour de la colonne met a jour en meme temps l'index ou dois je le reconstruire ?
    Cet a dire que si j'update 'toto ' en 'titi ' mon index sera remis a jour ?
    et que des lors
    select * from ma_table where col = 'titi '
    marchera :

    Merci,
    JR

  6. #6
    Expert confirm�
    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
    Par d�faut
    heureusement que votre index est mis � jour en m�me temps que la table (en admettant que la colonne soit effectivement index�e) !

    sinon, � quoi servirait-il :

  7. #7
    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
    Par d�faut
    Citation Envoy� par jrman
    Donc les chaines ne seront pas nettoyees, a priori ..., (bien que le surplus d'espace occupe par la transmission de ces espaces risque de s'averer embettant et que cette position sera peut etre revue).
    Si les espaces ne servent � rien, pourquoi refuser de les supprimer ??
    Comme je disais plus haut, une mise � jour globale pour l'existant
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    UPDATE latable SET lacolonne=TRIM(lacolonne);
    et un d�clencheur pour l'avenir, et le tour est jou�.

    Citation Envoy� par jrman
    Donc l'index pourrait repondre a mon besoin.
    J'ai une question qui me vient suite a cela ...

    Est ce que la mise a jour de la colonne met a jour en meme temps l'index ou dois je le reconstruire ?
    Cet a dire que si j'update 'toto ' en 'titi ' mon index sera remis a jour ?
    Oui !
    Citation Envoy� par jrman
    et que des lors
    select * from ma_table where col = 'titi '
    marchera :
    Non !
    Comme j'ai essay� de l'expliquer plus haut, l'index fonctionnel vous assurera des performances am�lior�es, mais ne vous permettra pas de faire "where col='titi'. Il faudra faire "where rtrim(col)='titi'.

    Sur les conditions d'utilisation des index fonctionnels, voir mon message en fin de ce sujet.

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Ao�t 2004
    Messages
    30
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 30
    Par d�faut
    Si les espaces ne servent � rien, pourquoi refuser de les supprimer ??
    Comme je disais plus haut, une mise � jour globale pour l'existant
    Excusez moi, je m'apercois que pour la solution 3 on s'ecarte de mon probleme.
    Mon probleme d'espace n'est pas sur la colonne de la table mais sur la valeur de recherche.

    La solution 2 est envisageable mais risque d'entrainer un surplus de stockage cela dit je crois que c'est encore la mieux sans changer le code.
    Par contre c'est pas tres propre, je crains que cela ne passe pas bien chez mes decideurs

    Pour la 1
    Ma contrainte principal est que je ne peux pas modifie ma requete, c'est pour cela que quant vous avez ecrit que des lors la recherche se fait par
    SELECT * FROM TEST WHERE rtrim(a)='toto';
    J'ai cru que vous parliez de ce que faisait Oracle de facon induite du a la presence de l'index et non en changeant ma requete.
    Je ne sais pas si j'ai ete clair mais bon en fait j'avais pas bien compris du fait qu'on ne parlait plus de mon probleme.

    Je parle de milliers de ligne de code SQL a retoucher donc c'est pour cela que je ne voudrais pas modifier mes requetes.

    Donc sans changer mon code je ne m'en sors pas de facon raisonnable en terme de cout de stockage : et d'un stockage qui plus est pas joli a regarder ...

    Merci,
    JR

  9. #9
    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
    Par d�faut
    Citation Envoy� par jrman
    Mon probleme d'espace n'est pas sur la colonne de la table mais sur la valeur de recherche.
    Oups, j'avais bien s�r compris l'inverse !!!

    Citation Envoy� par jrman
    La solution 2 est envisageable mais risque d'entrainer un surplus de stockage cela dit je crois que c'est encore la mieux sans changer le code.
    Par contre c'est pas tres propre, je crains que cela ne passe pas bien chez mes decideurs
    Effectivement, �a peut marcher. Le plus marrant, c'est que si j'avais compris votre question d�s le d�part (il suffisait de lire b�tement ce qui �tait �crit ), je n'aurais pas pens� � cette solution...

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Ao�t 2004
    Messages
    30
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 30
    Par d�faut
    Je vous remercie tous les deux d'avoir passe du temps sur mon soucis
    Je ne sais pas quelle solution va etre adoptee mais je crains qu'il n'y ait du remaniement de code dans l'air ca va refroidir du monde ...
    Car prendre le type Oracle char au lieu de varchar2 je le sens pas, enfin ce sera discute ...

    Pour info le char Unisys est egal au varchar UNIX + la gestion du \0 juste apres la valeur significative.

    En fait le embedded SQL Unisys travaille plus que le Embedded SQL Oracle
    du coup va falloir adapter le code avec ce qu'il manque je le crains ...

    Merci,
    JR

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Ao�t 2004
    Messages
    30
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 30
    Par d�faut
    Bonjour,

    Mon probleme a ete resolu par la modification du makefile de compilation Pro*C.

    En effet il suffit de modifier le comportement de pro*C vis a vis des host variables et de lui demander de ne pas completer par des espaces.
    Cela se passe dans la variable de makefile:
    PROCFLAGS= CODE=ANSI_C CHAR_MAP=STRING SQLCHECK= blablabla
    Soit la ligne de code suivante:
    EXEC SQL BEGIN DECLARE SECTION;
    char variable1[10];
    EXEC SQL END DECLARE SECTION;
    ...
    EXEC SQL select colonne1 into :variable1 from toto;
    Si la colonne1 de type Oracle char(10) contient 'abcde.....' ou varchar2(10) contient 'abcde'

    De base proc va inserer dans variable1 la valeur 'abcde.....\0'.
    La etait mon probleme car si je reutilisais cette valeur dans une jointure, je ne trouvais rien du tout.
    Avec l'option de compile (ci-dessus), proc va inserrer 'abcde\0'
    Des lors plus d'espace en trop a la fin, la valeur recuperee peut etre reutilisee dans une jointure ou transmise a l'appelant sans vilains espaces.
    C'est cool car y'a aucune ligne de code C ou SQL a changer.

    a+
    jrman

  12. #12
    Membre averti
    Femme Profil pro
    Administrateur de base de donn�es
    Inscrit en
    Avril 2004
    Messages
    46
    D�tails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Alpes Maritimes (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : Administrateur de base de donn�es

    Informations forums :
    Inscription : Avril 2004
    Messages : 46
    Par d�faut
    Bonjour
    Nous avons mis en place la solution donn�e ci-avant par jrman. Ca marche nickel pour les varchar2, mais maintenant on a des pbs avec les char, lorsqu'on utilise des host-variables.

    Voila un petit r�sum� :

    on a dans une table une colonne char(7) contenant 'TOTO' (on est d'accord, c'est padde donc il y a 'TOTO' suivi de 3 blancs )

    1- sous sqlplus, select * from table where col='TOTO' renvoie la ligne

    2- dans un programme C++, on g�n�re une requete statique
    select * from table where col='TOTO'
    l'ex�cution marche : on r�cup�re notre ligne

    3- toujours en C++, on g�n�re une requete avec host variable
    select * from table where col=:hv1
    ou l'on met 'TOTO' dans hv1

    l'ex�cution renvoie "no rows selected" - la ligne n'est pas trouv�e

    Y a-t-il quelque chose de particulier avec les host-variables ?
    NB : on traite de la meme facon les char et les varchar2...

    Merci d'avance

    Isa

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Ao�t 2004
    Messages
    30
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 30
    Par d�faut
    Bonjour,
    Je constate le meme comportement avec notre code Pro*C.
    Je n'ai pas eu le temps de chercher le pourquoi du comment et le remede s'il existe.
    Pour info, pourquoi utilisez vous des types char?
    Si vous trouvez, merci de nous faire part de la solution qui permet de ne pas filler la valeur de recherche avec des espaces.
    Je pense qu'il a un soucis avec la fin de la chaine, et du coup peut etre que les collations seraient une piste mais bon ...
    a+
    jrman

  14. #14
    Membre averti
    Femme Profil pro
    Administrateur de base de donn�es
    Inscrit en
    Avril 2004
    Messages
    46
    D�tails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Alpes Maritimes (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : Administrateur de base de donn�es

    Informations forums :
    Inscription : Avril 2004
    Messages : 46
    Par d�faut
    Bonjour

    On n'a pas resolu le probleme, je crois que les developpeurs ont enlev� l'option de precomp.
    En ce qui concerne l'utilisation de char, on a conserv� en char toutes les colonnes cl�s ou servant de critere de recherche/jointure (avec les varchar, si on saisit des blancs par erreur a la fin d'une chaine, les clauses where ne fonctionnent plus ). Or nous sommes dans un projet de migration (DB2-->Oracle) avec modification minimum du soft et l'on n'a pas le temps de modifier toutes les clauses where portant sur des chaines de caracteres.
    Mais bon d'un cot� comme de l'autre on a des problemes...

    Pour info, pourquoi utilisez vous des types char?
    Ma foi, du point de vue de nos developpeurs, la question est plutot : "mais pourquoi faut-il utiliser des varchar ?"

  15. #15
    Membre averti
    Profil pro
    Inscrit en
    Ao�t 2004
    Messages
    30
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 30
    Par d�faut
    Bonjour,
    De notre cot� je le rappelle nous migrons de Unisys/RDMS vers UNIX/Oracle.
    En fait nous avons etudie le comportement du type char RDMS, et de son comportement dans un type C Unisys, puis nous avons reproduit le meme comportement cot� Unix/Oracle.
    Je pense que d�j�, il faudrait faire cette �tude. Ensuite le choix char/varchar2 s'imposera de lui meme.
    Nous avons eu la chance de pouvoir le reproduire exactement grace a cette astuce de compilation, souhaitons que ce sera pareil de votre cot� afin d'�viter toute modif de code.
    a+
    jrman

  16. #16
    Membre Expert
    Avatar de LeoAnderson
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    2 938
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 2 938
    Par d�faut
    Attention cependant : il y a de fortes diff�rences entre CHAR et VARCHAR, notamment au niveau des op�rations de comparaisons mais surtout de la place disque occup�e (sans oublier les diff�rences de capacit�)

    A lire � ce sujet : CHAR versus VARCHAR2 Semantics

  17. #17
    Expert �minent
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    D�tails du profil
    Informations personnelles :
    �ge : 48
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Par d�faut
    CHAR existe toujours pour garantir la compatibilit� ascendante mais VARCHAR2 doit �tre utilis� pour les cha�nes de caract�res (ou CLOB )

  18. #18
    Membre averti
    Profil pro
    Inscrit en
    Ao�t 2004
    Messages
    30
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Ao�t 2004
    Messages : 30
    Par d�faut
    Bonjour,
    Megaculpa, je retire ce que j'ai dit
    Je ne constate pas le meme probleme que isa06.
    En revanche j'ai les meme conclusions dans nos contextes de migration.
    Pour ne pas avoir de probleme en recherche ou en resultat de select dans de l'embedded sql associe a du c/c++, le mieux est d'avoir des types char dans les programmes c/c++, et d'utiliser des types char dans les tables.
    Du coup y'a des blancs partout mais tous les select fonctionnent dans les 2 sens.
    Le type oracle/c/c++ varchar c'est une combinaison du type char c/c++ avec l'option de compile citee ci-avant. Car je le rappelle si tu select des varchar2 dans des char c/c++ tu te prends des blancs (sans l'option de compil).
    Tandis que faire des select de varchar2 dans des types varchar oracle pour c/c++ te renvoit la chaine exacte (modulo le null et sans l'option).

    a+
    jrman

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. Utiliser des valeur de cellule dans un userform
    Par swissmade dans le forum Macros et VBA Excel
    R�ponses: 4
    Dernier message: 05/07/2007, 19h38
  2. R�ponses: 2
    Dernier message: 04/05/2007, 10h55
  3. R�ponses: 2
    Dernier message: 02/05/2007, 17h07
  4. R�ponses: 13
    Dernier message: 21/09/2005, 15h39
  5. R�cup�rer des valeurs de checkbox dans MySQL
    Par digger dans le forum SQL Proc�dural
    R�ponses: 1
    Dernier message: 05/09/2005, 14h58

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