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;
4 Réponses :
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);
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!
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
.
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
où t
est l'alias de la table tmp
, m
est pour main_table
.
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