J'utilise la fonction REPLACE
dans Oracle pour remplacer les valeurs de ma chaîne comme;
SELECT REPLACE('THE NEW VALUE IS #VAL1#','#VAL1#','55') from dual
Donc, c'est OK pour remplacer une valeur, mais qu'en est-il de 20+, dois-je utiliser la fonction 20+ REPLACE
ou existe-t-il une solution plus pratique.
Toutes les idées sont les bienvenues.
Même si ce fil est ancien, c'est le premier sur Google, donc je posterai un équivalent Oracle à la fonction implémentée ici, en utilisant des expressions régulières.
Est plus rapide que replace () imbriqué et beaucoup plus propre.
Pour remplacer les chaînes 'a', 'b', 'c' par 'd' dans une colonne de chaîne d'une table donnée
select regexp_replace(string_col,'a|b|c','d') from given_table
Ce n'est rien d'autre qu'une expression régulière pour plusieurs modèles statiques avec l'opérateur 'ou'.
Méfiez-vous des caractères spéciaux regexp!
Gardez à l'esprit les conséquences
SELECT REPLACE(REPLACE('TEST123','123','456'),'45','89') FROM DUAL;
remplacera le 123 par 456, puis trouvera qu'il peut remplacer le 45 par 89. Pour une fonction qui avait un résultat équivalent, il faudrait dupliquer la priorité (c'est-à-dire remplacer les chaînes dans le même ordre).
De même, prendre une chaîne 'ABCDEF' et lui demander de remplacer 'ABC' par '123' et 'CDE' par 'xyz' devra toujours tenir compte d'une priorité pour déterminer si elle est passée à '123EF' ou ABxyzF '.
En bref, il serait difficile de trouver quelque chose de générique qui serait plus simple qu'un REMPLACEMENT imbriqué (même si quelque chose qui était plus une fonction de style sprintf serait un ajout utile).
La réponse acceptée à comment remplacer plusieurs chaînes ensemble dans Oracle suggère d'utiliser des instructions imbriquées REPLACE
, et je ne pense pas qu'il existe une meilleure façon.
Si vous allez en faire un usage intensif, vous pourriez envisager d'écrire votre propre fonction:
CREATE TYPE t_text IS TABLE OF VARCHAR2(256);
CREATE FUNCTION multiple_replace(
in_text IN VARCHAR2, in_old IN t_text, in_new IN t_text
)
RETURN VARCHAR2
AS
v_result VARCHAR2(32767);
BEGIN
IF( in_old.COUNT <> in_new.COUNT ) THEN
RETURN in_text;
END IF;
v_result := in_text;
FOR i IN 1 .. in_old.COUNT LOOP
v_result := REPLACE( v_result, in_old(i), in_new(i) );
END LOOP;
RETURN v_result;
END;
puis utilisez-le comme ceci:
SELECT multiple_replace( 'This is #VAL1# with some #VAL2# to #VAL3#',
NEW t_text( '#VAL1#', '#VAL2#', '#VAL3#' ),
NEW t_text( 'text', 'tokens', 'replace' )
)
FROM dual
Ceci est du texte avec quelques jetons à remplacer
Si tous vos jetons ont le même format ('#VAL' || i || '#'
), vous pouvez omettre le paramètre in_old
et utilisez plutôt votre compteur de boucles.
C'est un vieux post, mais j'ai fini par utiliser les pensées de Peter Lang, et j'ai fait une approche similaire, mais pourtant différente. Voici ce que j'ai fait:
CREATE OR REPLACE FUNCTION multi_replace(
pString IN VARCHAR2
,pReplacePattern IN VARCHAR2
) RETURN VARCHAR2 IS
iCount INTEGER;
vResult VARCHAR2(1000);
vRule VARCHAR2(100);
vOldStr VARCHAR2(50);
vNewStr VARCHAR2(50);
BEGIN
iCount := 0;
vResult := pString;
LOOP
iCount := iCount + 1;
-- Step # 1: Pick out the replacement rules
vRule := REGEXP_SUBSTR(pReplacePattern, '[^/]+', 1, iCount);
-- Step # 2: Pick out the old and new string from the rule
vOldStr := REGEXP_SUBSTR(vRule, '[^=]+', 1, 1);
vNewStr := REGEXP_SUBSTR(vRule, '[^=]+', 1, 2);
-- Step # 3: Do the replacement
vResult := REPLACE(vResult, vOldStr, vNewStr);
EXIT WHEN vRule IS NULL;
END LOOP;
RETURN vResult;
END multi_replace;
Ensuite, je peux l'utiliser comme ceci:
SELECT multi_replace(
'This is a test string with a #, a $ character, and finally a & character'
,'#=%23/$=%24/&=%25'
)
FROM dual
Cela fait en sorte que je puisse utiliser n'importe quel caractère/chaîne avec n'importe quel caractère/chaîne.
J'ai écrit un article à ce sujet sur mon blog.
Dans le cas où toutes vos chaînes source et de remplacement ne comportent qu'un seul caractère, vous pouvez simplement utiliser la fonction TRANSLATE
:
SELECT translate('THIS IS UPPERCASE', 'THISUP', 'thisup')
FROM DUAL
Voir la documentation Oracle pour plus de détails.
J'ai créé une fonction Oracle de chaîne de remplacement multi générale par une table de varchar2 comme paramètre. Le varchar sera remplacé pour la valeur de rownum de position de la table.
Par exemple:
Text: Hello {0}, this is a {2} for {1}
Parameters: TABLE('world','all','message')
Résultats:
Hello world, this is a message for all.
Vous devez créer un type:
CREATE OR REPLACE TYPE "TBL_VARCHAR2" IS TABLE OF VARCHAR2(250);
La fonction est:
CREATE OR REPLACE FUNCTION FN_REPLACETEXT(
pText IN VARCHAR2,
pPar IN TBL_VARCHAR2
) RETURN VARCHAR2
IS
vText VARCHAR2(32767);
vPos INT;
vValue VARCHAR2(250);
CURSOR cuParameter(POS INT) IS
SELECT VAL
FROM
(
SELECT VAL, ROWNUM AS RN
FROM (
SELECT COLUMN_VALUE VAL
FROM TABLE(pPar)
)
)
WHERE RN=POS+1;
BEGIN
vText := pText;
FOR i IN 1..REGEXP_COUNT(pText, '[{][0-9]+[}]') LOOP
vPos := TO_NUMBER(SUBSTR(REGEXP_SUBSTR(pText, '[{][0-9]+[}]',1,i),2, LENGTH(REGEXP_SUBSTR(pText, '[{][0-9]+[}]',1,i)) - 2));
OPEN cuParameter(vPos);
FETCH cuParameter INTO vValue;
IF cuParameter%FOUND THEN
vText := REPLACE(vText, REGEXP_SUBSTR(pText, '[{][0-9]+[}]',1,i), vValue);
END IF;
CLOSE cuParameter;
END LOOP;
RETURN vText;
EXCEPTION
WHEN OTHERS
THEN
RETURN pText;
END FN_REPLACETEXT;
/
Usage:
TEXT_RETURNED := FN_REPLACETEXT('Hello {0}, this is a {2} for {1}', TBL_VARCHAR2('world','all','message'));