Oracle中的多重替换功能

Oracle中的多重替换功能,oracle,replace,Oracle,Replace,我正在使用oracle中的REPLACE函数替换字符串中的值 SELECT REPLACE('THE NEW VALUE IS #VAL1#','#VAL1#','55') from dual 所以替换一个值是可以的,但是20+怎么样,我应该使用20+replace函数还是有更实用的解决方案 欢迎提出任何意见 公认的答案建议使用嵌套的REPLACE语句,我认为没有更好的方法 如果你要充分利用这一点,你可以考虑写你自己的函数: CREATE TYPE t_text IS TABLE OF VA

我正在使用oracle中的
REPLACE
函数替换字符串中的值

 SELECT REPLACE('THE NEW VALUE IS #VAL1#','#VAL1#','55') from dual
所以替换一个值是可以的,但是20+怎么样,我应该使用20+
replace
函数还是有更实用的解决方案

欢迎提出任何意见

公认的答案建议使用嵌套的
REPLACE
语句,我认为没有更好的方法

如果你要充分利用这一点,你可以考虑写你自己的函数:

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;
  SELECT translate('THIS IS UPPERCASE', 'THISUP', 'thisup') 
  FROM DUAL
这是带有一些要替换的标记的文本


如果所有令牌的格式相同(
“|VAL”| | i | | |“#”
),则可以在旧的中省略参数
,而使用循环计数器。

请记住后果

SELECT REPLACE(REPLACE('TEST123','123','456'),'45','89') FROM DUAL;
将123替换为456,然后发现它可以将45替换为89。 对于具有等效结果的函数,它必须复制优先级(即以相同顺序替换字符串)

类似地,获取字符串“ABCDEF”并指示其将“ABC”替换为“123”,将“CDE”替换为“xyz”,仍然需要考虑优先级,以确定它是转到“123EF”还是ABxyzF”


简言之,很难想出比嵌套替换更简单的通用方法(尽管更像sprintf风格的函数可能是一个有用的补充)。

这是一篇老文章,但我最终使用了Peter Lang的思想,并采用了类似但又不同的方法。以下是我所做的:

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;
然后我可以这样使用它:

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
SELECT  multi_replace(
                        'This is a test string with a #, a $ character, and finally a & character'
                        ,'#=%23/$=%24/&=%25'
        )
FROM dual
这使得我可以使用任何字符/字符串来访问任何字符/字符串


我在我的博客上写了一篇关于这一点的文章。

即使这个线程很旧,也是Google上的第一个线程,因此我将发布一个与这里实现的函数相当的Oracle,使用正则表达式

比嵌套的replace()快得多,而且更干净

将给定表中字符串列中的字符串“a”、“b”、“c”替换为“d”

select regexp_replace(string_col,'a|b|c','d') from given_table
它只是几个静态模式的正则表达式,带有'or'运算符


小心regexp特殊字符

如果所有源字符串和替换字符串只有一个字符长,您只需使用
TRANSLATE
功能:

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;
  SELECT translate('THIS IS UPPERCASE', 'THISUP', 'thisup') 
  FROM DUAL

有关详细信息,请参阅。

我已通过varchar2作为参数的表格创建了一个通用的多重替换字符串Oracle函数。 varchar将替换为表的位置rownum值

例如:

Text: Hello {0}, this is a {2} for {1}
Parameters: TABLE('world','all','message')
返回:

Hello world, this is a message for all.
您必须创建一个类型:

CREATE OR REPLACE TYPE "TBL_VARCHAR2" IS TABLE OF VARCHAR2(250);
其功能是:

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;
/
用法:

TEXT_RETURNED := FN_REPLACETEXT('Hello {0}, this is a {2} for {1}', TBL_VARCHAR2('world','all','message'));

谢谢你的回答。除了在调用中指定翻译,您还可以使用如下所示的光标来执行此操作

create or replace function character_substitutions (input_str varchar2)
return varchar2

as

v_result VARCHAR2(4000);

cursor c_translate_table is
    select '&' as symbol_to_replace, 'amp' as symbol_in_return_string from dual
    union all
    select '/' as symbol_to_replace, '_' as symbol_in_return_string from dual
    union all
    select '"' as symbol_to_replace, 'in' as symbol_in_return_string from dual
    union all
    select '%' as symbol_to_replace, 'per' as symbol_in_return_string from dual
    union all
    select '.' as symbol_to_replace, '_' as symbol_in_return_string from dual;
    
begin

v_result := input_str;

for r_translate in c_translate_table loop

    v_result := REPLACE( v_result, r_translate.symbol_to_replace, r_translate.symbol_in_return_string);

end loop;

return v_result;

end;
/

@阿德南:不客气,但是在接受我的答案之前我会等待一段时间-可能还有其他/更好的答案:)
RETURN VARCHAR2 DETERMINISTIC
可能会更快。这个简单的解决方案比编写自己的函数来完成已经实现的任务要好得多。我同意这是关于实际问题的更好答案问题被问得好多了!谢谢!这将用
d
替换
a
b
c
中的任何一个,但可能的要求是用一个单独的值来替换每个值,以允许从模板构建字符串,例如
“No”VAL1“存在于此#VAL2”
传递
(“供应商”、“奶酪类型”)
。同意,但问题并不特别清楚。如果您想替换\n、\t、\r之类的内容,您必须这样做:
REGEXP\u替换(列,'\x09 | \x0A | \x0D','')为列
,这是结尾的两个单引号。。