2015-04-01 85 views
0

注意:此问题最初是在C++ regexp_replace(请参阅here)的环境中提出的。然而,我想到它也可能对神谕世界感兴趣。这个问题的措辞已经得到了原作者的许可。Oracle:是否有支持嵌入式代码的REGEX_REPLACE变体?

Perl有e正则表达式修饰符,它允许使用Perl代码而不仅仅是一个字符串来表示替换:http://perldoc.perl.org/perlretut.html#Search-and-replace虽然该示例并不是最大的,因为有交换机可以完成此操作。对于那些你们谁了解Perl的下面是一个更有意义的例子:

$string = "StackOverflow user: Old Faithful"; 

$string =~ s/:\s*(.*)$/$1 == "Old Faithful" ? ": ".$1." is AWESOME!" : ": ".$1." is ???"/e; 

print $string; #Will print "StackOverflow user: Old Faithful is AWESOME!" 

是否有regex_replace变体(PL)的Sql,让我做同样的事情?如代码内联代替。

回答

2

不幸的是,REGEX_REPLACE不支持动态生成的替换字符串。

但是,您可以靠近。这个答案包含了3个相同想法的变体。简而言之:

  • 变形例1:静态
    简单,仅在表达式语法,SQL兼容,性能恶梦

  • 变形例2的计算:静态+函数调用

    简单,复杂的计算,与SQL兼容,性能噩梦;
    创建所需功能/包的权限。

  • 变化3:动态
    复杂,执行代码的最大灵活性,与sql兼容,性能......你猜对了。

的所有方法的基本思想是利用REGEXP_SUBSTR获得的捕获组的内容保持这些内容喂到代码计算与它实际上取代了数据。 在Variation 1中,此代码本身就是表达式,变体2将此代码隐藏在函数体中,变体3将其作为其周围的动态plsql块来实现。

变体1(静态)

使用REGEXP_SUBSTR获得的捕获基团含量保持和进料的表达来处理相应地这样的数据:

set serveroutput on 
DECLARE 
    text_orig_yep VARCHAR2(1000) := 'StackOverflow user: Old Faithful'; 
    text_orig_nay VARCHAR2(1000) := 'StackOverflow user: Some Nobody'; 
    text_pattern VARCHAR2(1000) := ':\s*(.*)$'; 
    text_repl  VARCHAR2(1000); 
BEGIN 
    text_repl := 
     REGEXP_REPLACE (
      text_orig_yep 
      , text_pattern 
      , CASE REGEXP_SUBSTR(text_orig_yep, text_pattern, 1, 1, '', 1) 
       WHEN 'Old Faithful' THEN REGEXP_SUBSTR(text_orig_yep, text_pattern, 1, 1, '', 1)||' is AWESOME!' 
       ELSE      REGEXP_SUBSTR(text_orig_yep, text_pattern, 1, 1, '', 1)||' is ???' 
      END 
     ); 
    dbms_output.put_line (text_repl); 
    text_repl := 
     REGEXP_REPLACE (
      text_orig_nay 
      , text_pattern 
      , CASE REGEXP_SUBSTR(text_orig_nay, text_pattern, 1, 1, '', 1) 
       WHEN 'Old Faithful' THEN REGEXP_SUBSTR(text_orig_yep, text_pattern, 1, 1, '', 1)||' is AWESOME!' 
       ELSE      REGEXP_SUBSTR(text_orig_yep, text_pattern, 1, 1, '', 1)||' is ???' 
      END 
     ); 
    dbms_output.put_line (text_repl); 
END; 
/
show error 

变体2(静态+函数调用)

使用REGEXP_SUBSTR获取捕获组内容并提供计算结果的功能。通过这种方式,您可以执行复杂的计算,这些计算是不可能的或繁琐的,以表示为plsql表达式。

set serveroutput on 
CREATE OR REPLACE FUNCTION test_rreval (match_1 IN VARCHAR2) RETURN VARCHAR2 
IS 
BEGIN 
    RETURN 
     CASE match_1 
      WHEN 'Old Faithful' THEN match_1||' is AWESOME!' 
      ELSE      match_1||' is ???' 
     END 
    ; 
END test_rreval; 
/
show error 

DECLARE 
    text_orig_yep VARCHAR2(1000) := 'StackOverflow user: Old Faithful'; 
    text_orig_nay VARCHAR2(1000) := 'StackOverflow user: Some Nobody'; 
    text_pattern VARCHAR2(1000) := ':\s*(.*)$'; 
    text_repl  VARCHAR2(1000); 
BEGIN 
    text_repl := 
     REGEXP_REPLACE (
      text_orig_yep 
      , text_pattern 
      , test_rreval (REGEXP_SUBSTR(text_orig_yep, text_pattern, 1, 1, '', 1)) 
     ); 
    dbms_output.put_line (text_repl); 
    text_repl := 
     REGEXP_REPLACE (
      text_orig_nay 
      , text_pattern 
      , test_rreval (REGEXP_SUBSTR(text_orig_nay, text_pattern, 1, 1, '', 1)) 
     ); 
    dbms_output.put_line (text_repl); 
END; 
/
show error 

变3(动态)

您可以通过生成动态PLSQL块出示你result.As一个振作你可以保持接近获得在性能和可维护性成本最大的灵活性perl语法(但您可以相应地调整变体2)。

set serveroutput on 
DECLARE 
    text_orig_yep VARCHAR2(1000) := 'StackOverflow user: Old Faithful'; 
    text_orig_nay VARCHAR2(1000) := 'StackOverflow user: Some Nobody'; 
    text_pattern VARCHAR2(1000) := ':\s*(.*)$'; 
    text_repl  VARCHAR2(1000); 
    dyncode  VARCHAR2(32000); 
BEGIN 
    dyncode := 'DECLARE "$1" VARCHAR2(32000) := :1; BEGIN :outvar := REGEXP_REPLACE (:text_orig, :text_pattern, CASE "$1" WHEN ''Old Faithful'' THEN "$1"||'' is AWESOME!'' ELSE "$1"||'' is ???'' END); END;'; 
    EXECUTE IMMEDIATE dyncode 
       USING IN REGEXP_SUBSTR(text_orig_yep, text_pattern, 1, 1, '', 1) 
        , OUT text_repl 
        , IN text_orig_yep 
        , IN text_pattern 
        ; 
    dbms_output.put_line (text_repl); 
    EXECUTE IMMEDIATE dyncode 
       USING IN REGEXP_SUBSTR(text_orig_nay, text_pattern, 1, 1, '', 1) 
        , OUT text_repl 
        , IN text_orig_nay 
        , IN text_pattern 
        ; 
    dbms_output.put_line (text_repl); 
END; 
/
show error 
相关问题