将反向引用传递给Oracle Regexp中的另一个函数

时间:2013-10-22 17:09:31

标签: sql regex oracle oracle11g

我正在尝试运行vanilla regexp_replace,除了使用反向引用值动态选择替换字符串。

为了给出更多的上下文,我(在同一个表的两列中,为了简化事情)两个字符串。第一个包含占位符,如{1},{2}作为字符串文字本身的一部分;需要用第二个字符串的相应子字段替换(在用一些常量分隔符标记它之后,比如'|')。

所以,如果我们有:

Str1 ='快速褐色{1}跳过懒惰的{2}。

Str2 ='fox | dog'

我们需要结果......我相信你明白了。

在一个理想的世界中,Oracle(11g Enterprise 64位)可以让我这样做:


with x as (select 'The quick brown {1} jumps over the lazy {2}.' col1, 'fox|dog' col2 from dual)
select regexp_replace(x.col1, '({[0-9]+})', regexp_substr(x.col2,'[^|]+',1,'\1')) as result
from x

但是,第二个regexp_substr无法识别外部regexp_replace调用的反向引用并抛出ORA-17222:无效数字。

我不想创建存储过程或函数,因为我的业务案例是创建一个包含此数据的(可能是物化的)视图。我宁愿有一个可以做到这一点的单线。

查看各种论坛,Oracle可能不支持这种反向引用,因此问题标题可能有点误导 - 如果你可以指向另一种选择(不使用其他DDL),那也就是这样。我在编程方面经验丰富,但在Oracle本身并不熟悉,所以请保持温和!

有些浏览表明人们倾向于使用模糊条款和xmltables之类的模糊事物(在今天之前没有听说过)用于复杂的正则表达式拼图,但我认为可能有些东西很简单,我错过了。

2 个答案:

答案 0 :(得分:2)

我会使用简单的PL / SQL函数 - 这只是一个循环来迭代占位符并替换变量。您也可以在SQL中使用它来定义视图。

如果你真的想要纯SQL解决方案,这里有一个使用常见的表表达式(它绝对不是很简单):

with data as (
  select 1 id, 'The quick brown {1} jumps over the lazy {2} and {3}.' txt, 'fox|dog|cat' || '|' vars from dual
  union all
  select 2 id, 'Hello {1}' txt, 'world' || '|' vars from dual
),

recursive (id, txt, vars, i) as (
  select id, txt, vars, 1 i
  from data
  union all
  select id,
         replace (txt,
                  '{' || i || '}',
                  regexp_substr(vars, '[^|]+')),
         substr(vars, instr(vars, '|') + 1),
         i+1
  from recursive
  where instr(vars, '|') > 0)

select txt
from (select txt, row_number() over (partition by id order by i desc) rn
      from recursive)
where rn = 1;

答案 1 :(得分:0)

实际上,你应该尝试这个(我之前的回答忘了在regexp_substr中捕获):

with x as (select 'The quick brown {1} jumps over the lazy {2}.' col1, 'fox|dog' col2 from dual) select regexp_replace(x.col1, '({[0-9]+})', regexp_substr(x.col2,'([^|]+)',1,1,'i',1)) as result from x;