1
votes

Comment échapper des caractères spéciaux dans une chaîne lors de l'exécution d'une jointure interne dans Oracle?

Il existe une table temporaire avec des mots et des identifiants. Je dois joindre ces mots à la table principale pour obtenir leurs identifiants. Mais la table temporaire peut avoir des caractères spéciaux ainsi que des mots tels que des chiffres. / .digits /, chiffres / chiffres, / -digits / chiffres-. Dans ce cas, la jointure interne ne renverrait pas les chiffres de valeur. Comment échapper à ces caractères pour être sûr que la valeur "digits" est renvoyée?

Je dois conserver les caractères spéciaux dans la table tmp. Il suffit de les échapper lors de la connexion.

ID    WORD      WORD_ID
1     digits     111
2     digits.    111
3     .digits-   111
Here is the test data:

CREATE TABLE TMP
   (ID NUMBER,
    WORD VARCHAR2(4000 BYTE),
    WORD_ID NUMBER
);

CREATE TABLE main_table
   (ID NUMBER,
    WORD VARCHAR2(4000 BYTE));

insert into tmp(id,word) values ( 1, 'digits' );
insert into tmp(id,word) values ( 2, 'digits.' );
insert into tmp(id,word) values ( 3, '.digits-' );

insert into main_table values( 111, 'digits');

Le résultat attendu est de mettre à jour word_id dans la table tmp à partir de main_table. P >

for t in (select id,word from tmp)
LOOP
      update tmp a
      set a.word_id = (
      select b.id
      from main_table b
      where lower(a.word) = lower(b.word)
      and rownum =1
     )
      where a.word in (select word from tmp where word = t.word);
END LOOP;  


0 commentaires

4 Réponses :


0
votes

Vous pouvez essayer d'utiliser REGEXP_REPLACE pour supprimer tous les caractères non alphanumériques avant de faire la comparaison:

UPDATE tmp a
SET a.word_id = (SELECT b.id
                 FROM main_table b
                 WHERE REGEXP_REPLACE(a.word, '[^A-Za-z0-9]', '') = b.word);


2 commentaires

Merci Tim. Cela a fonctionné. Le tableau est mis à jour avec son identifiant de mot maintenant. J'essaye maintenant de remplacer la sous-chaîne "digit" dans "digits". comme www.xxx.com/digits/123digits . Je m'attends à "." pour ne pas faire partie de ce remplacement. Je recherche votre aide pour échapper aux caractères spéciaux lors du remplacement.


Génial. Ouvrez une nouvelle question et je suis sûr que quelqu'un pourra vous aider!



0
votes

TRANSLATE est votre ami ici.

Définissez simplement les caractères à conserver - ils sont définis de manière identique dans les deux chaînes TRANSLATE et les caractères qui doivent être supprimés, ils sont mappés sur NULL.

Un exemple d'une telle transformation est présenté dans cette requête

select tmp.word tmp_word,  main_table.word main_word
from tmp
left outer join  main_table
on translate(lower(tmp.word),'abcdefghijklmnopqrstuvwxyz.-#*+',
                          'abcdefghijklmnopqrstuvwxyz') = main_table.word

La jointure ressemblera à quelque chose comme ceci

select word,
translate(lower(word),'abcdefghijklmnopqrstuvwxyz.-#*+',
                      'abcdefghijklmnopqrstuvwxyz') word_clean
from tmp;

WORD       WORD_CLEAN
---------- ----------
digits     digits    
digits.    digits    
.digits-   digits

Notez que j'utilise lower pour éliminer les majuscules - ajustez si nécessaire.

Notez également que l'option TRANSLATE donnera de bien meilleures performances que l'option avec REGEXP.


0 commentaires

0
votes

Une option consisterait à utiliser le modèle [^ [: alnum:]] POSIX dans la fonction regexp_replace () dans la fonction WHERE condition de la sous-sélection dans l'instruction UPDATE :

regexp_replace (t.word, '[^ [: alnum:]]') = m.word

t est l'alias de la table tmp , m est pour main_table .


0 commentaires

0
votes

Voici une autre façon de le faire.

 update tmp a
      set a.word_id = (
      select b.id
      from main_table b
      where lower(a.word) like concat(concat('%',b.word),'%') 
      and rownum =1


0 commentaires