1

我正在尝试运行一个普通的 regexp_replace,除了替换字符串是使用反向引用值动态选择的。

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

所以,如果我们有:

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

Str2 = '狐狸|狗'

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

在理想情况下,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:invalid number。

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

查看各种论坛,Oracle 可能不支持这种反向引用传递,因此问题标题可能有点误导 - 如果您能指出我的另一种选择(不诉诸其他 DDL),那也一样。我有编程经验,但对 Oracle 本身没有经验,所以请温柔一点!

一些浏览表明人们倾向于使用诸如 MODEL 子句和 xmltables(今天之前没有听说过它们)之类的晦涩的东西来解决复杂的正则表达式难题,但我认为我可能遗漏了一些简单得尴尬的东西。

4

2 回答 2

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;
于 2013-10-22T21:31:09.447 回答
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;
于 2014-03-14T16:02:27.300 回答