2008-09-17 5 views
9

J'ai une chaîne provenant d'une table comme "ne peut pas payer {1}, comme votre paiement {2} en raison de {3}". Je veux remplacer {1} avec une certaine valeur, {2} avec une certaine valeur et {3} avec une certaine valeur.comment remplacer plusieurs chaînes ensemble dans Oracle

Est-il possible de remplacer tous les 3 dans une fonction de remplacement? ou est-ce que je peux écrire directement une requête et obtenir une valeur remplacée? Je veux remplacer ces chaînes dans la procédure stockée Oracle la chaîne d'origine provient d'un de ma table je fais juste sélectionner sur cette table

puis je veux remplacer les valeurs {1}, {2}, {3} de cette chaîne à l'autre valeur que j'ai une autre table

+0

en double possible de [Multiple REMPLACER fonction dans Oracle] (https://stackoverflow.com/questions/2947623/multiple-replace-function-in-oracle) – Joaquinglezsantos

Répondre

12

Bien qu'il soit un appel, vous pouvez imbriquer les replace() appels:

SET mycol = replace(replace(mycol, '{1}', 'myoneval'), '{2}', mytwoval) 
+0

La seconde mytwoval manque-t-elle des guillemets simples? –

+0

@SimonTheCat Vous avez raison! (Sauf si mytwoval était une variable) – hamishmcn

-1

Si vous faites cela à l'intérieur d'une sélection, vous pouvez Il suffit de le reconstituer, si vos valeurs de remplacement sont des colonnes, en utilisant la concaténation de chaînes.

4

S'il y a beaucoup de variables à remplacer et que vous les avez dans une autre table et si le nombre de variables est variable, vous pouvez utiliser un CTE récursif pour les remplacer. Un exemple ci-dessous. Dans la table fg_rulez vous mettez les cordes avec leur remplacement. Dans la table fg_data, vous avez vos chaînes d'entrée.

set define off; 
drop table fg_rulez 
create table fg_rulez as 
    select 1 id,'<' symbol, 'less than' text from dual 
    union all select 2, '>', 'great than' from dual 
    union all select 3, '$', 'dollars' from dual 
    union all select 4, '&', 'and' from dual; 
drop table fg_data; 
create table fg_Data AS(
    SELECT 'amount $ must be < 1 & > 2' str FROM dual 
    union all 
    SELECT 'John is > Peter & has many $' str FROM dual 
    union all 
    SELECT 'Eliana is < mary & do not has many $' str FROM dual 

    ); 


WITH q(str, id) as (
    SELECT str, 0 id 
    FROM fg_Data 
    UNION ALL 
    SELECT replace(q.str,symbol,text), fg_rulez.id 
    FROM q 
    JOIN fg_rulez 
    ON q.id = fg_rulez.id - 1 
) 
SELECT str from q where id = (select max(id) from fg_rulez); 

Ainsi, un seul replace.

Résultat:

amount dollars must be less than 1 and great than 2 
John is great than Peter and has many dollars 
Eliana is less than mary and do not has many dollars 

Le symbole de la terminologie au lieu de la variable provient de this duplicated question.

Oracle 11gR2

+0

Aliasing dans la clause WITH est pris en charge depuis Oracle 11gR2. – Stephan

+1

IMH c'est une excellente réponse car elle répond au point qui a malheureusement été référencé obliquement dans la question, à savoir permettre de mettre à jour les termes remplacés sans éditer la requête proprement dite (ce qui est un scénario utile dans un environnement contrôlé). – Neil

1

Si le nombre de valeurs à remplacer est trop grand ou vous devez être en mesure pour le maintenir facilement, vous pouvez également diviser la chaîne, utiliser une table de dictionnaire et enfin agréger les résultats

Dans l'exemple ci-dessous je suppose que les mots de votre chaîne sont séparés par blankspaces et le nombre de mots dans la chaîne ne sera pas plus grand que 100 (tableau pivot cardinalité)

with Dict as 
(select '{1}' String, 'myfirstval' Repl from dual 
    union all 
    select '{2}' String, 'mysecondval' Repl from dual 
    union all 
    select '{3}' String, 'mythirdval' Repl from dual 
    union all 
    select '{Nth}' String, 'myNthval' Repl from dual 

) 
,MyStrings as 
(select 'This is the first example {1} ' Str, 1 strnum from dual 
    union all 
    select 'In the Second example all values are shown {1} {2} {3} {Nth} ', 2 from dual 
    union all 
    select '{3} Is the value for the third', 3 from dual 
    union all 
    select '{Nth} Is the value for the Nth', 4 from dual 
) 
,pivot as (
    Select Rownum Pnum 
    From dual 
    Connect By Rownum <= 100 
) 
,StrtoRow as 
(
SELECT rownum rn 
     ,ms.strnum 
     ,REGEXP_SUBSTR (Str,'[^ ]+',1,pv.pnum) TXT 
    FROM MyStrings ms 
     ,pivot pv 
where REGEXP_SUBSTR (Str,'[^ ]+',1,pv.pnum) is not null 
) 
Select Listagg(NVL(Repl,TXT),' ') within group (order by rn) 
from 
(
Select sr.TXT, d.Repl, sr.strnum, sr.rn 
    from StrtoRow sr 
     ,dict d 
where sr.TXT = d.String(+) 
order by strnum, rn 
) group by strnum 
+0

C'est une bonne utilisation de la clause WITH et des félicitations pour l'implémentation d'une solution SQL seule, mais le résultat est encore assez difficile (pour certains d'entre nous) à analyser! Cela semble bien fonctionner, mais si je l'implémente dans mon code, je ne demanderais pas à un collègue de l'examiner pour vérifier s'il est correct. Ils me tireraient dessus! :-) – StewS2

Questions connexes