Oracle 中是否有 Regep_replace 的组限制? (有 regexp_replace 个问题)

Is there a group limit for Regep_replace in Oracle? (with regexp_replace issue)

此刻我得到了一个很长的输入字符串,我想用 regexp_replace 反转它。通常我用这个替换字符串位置(从 PL/SQL 的 begin 子句中)

variable:= regexp_replace(variable, '(.+) (.+) (.+) (.+)', '   ');

在这种情况下,我的变量将以相反的顺序被替换,并且它有效。现在我的问题和我的问题是。加群有限制吗?因为我得到了这个字符串:

US 816909877808647715885542447721 UOPX

我将这个字符串作为输入输入到我的函数中,函数开始转换这个字符串。在某个时候,它使四人一组(这也很有效)。为此,我使用以下内容:

variable:= regexp_replace(variable, '(....)', ' ');

这导致下一个输出:

3630 3139 3634 8169 0987 7808 6477 1588 5542 4477 21 -- also did ASCII to number

所以现在我得到了我想要的。整个字符串被分成四个一组。但现在我的问题是,当我想用​​这段代码反转所有这 11 个组时:

  convertedStudentNumber := regexp_replace(convertedStudentNumber, '(.+) (.+) (.+) (.+) (.+) (.+) (.+) (.+) (.+) (.+) (.+)', '          ');

这是我的结果:

36301 36300 5542 1588 6477 7808 0987 8169 3634 3139 3630

当我用 9 组反转组时,如下所示:

  variable:= regexp_replace(variable, '(.+) (.+) (.+) (.+) (.+) (.+) (.+) (.+) (.+)', '        ');

这是我的结果:

21 4477 5542 1588 6477 7808 0987 8169 3630 3139 3634

我得到的 9 个组更接近我想要实现的目标。但是最后三组仍然无法以某种奇怪的方式修复。

21 4477 5542 1588 6477 7808 0987 8169 [3630 3139 3634]--won't work.

简而言之。这是我想按组反转的字符串

3630 3139 3634 8169 0987 7808 6477 1588 5542 4477 21

但我不会比

更进一步
21 4477 5542 1588 6477 7808 0987 8169 [3630 3139 3634]

Oracle 只允许 9 个反向引用,因此您将无法使用 \10 或更高版本。 但是,为什么不拿你的字符串并反转每个组呢?

例如:

create table test (
   v varchar(100)
);

insert into test values ('363031393634816909877808647715885542447721');

select v, regexp_replace(v, '([0-9]{4})', ' ') as v_replaced
from test;

结果:

3630 3139 3634 8169 0987 7808 6477 1588 5542 4477 21

现在反转每个数字组的顺序(技术取自这里:Reverse String Word by Word using SQL):

WITH str_tab(str1, rn) AS
(SELECT regexp_substr(str, '[^\[:space:]]+', 1, LEVEL), 
        LEVEL 
   FROM (SELECT regexp_replace(v, '([0-9]{4})', ' ') str
           FROM test) tab
CONNECT BY LEVEL <= LENGTH(str) - LENGTH(REPLACE(str, ' ')) + 1)
SELECT listagg(str1, ' ') WITHIN GROUP (ORDER BY rn DESC) AS new_text
  FROM str_tab;

结果:

21 4477 5542 1588 6477 7808 0987 8169 3634 3139 3630

下面是 PL/SQL 脚本中的相同内容:

declare
  variable varchar(100) := '363031393634816909877808647715885542447721';
begin
  -- You don't need these next two lines.
  -- They just show you the variable modified to have a space
  -- after every four digits.  You can remove these lines.
  variable := regexp_replace(variable, '([0-9]{4})', ' ');
  dbms_output.put_line('variable: ' || variable);

  -- Get the reversed string INTO the variable
  WITH str_tab(str1, rn) AS
  (SELECT regexp_substr(str, '[^\[:space:]]+', 1, LEVEL),  LEVEL 
   FROM (SELECT regexp_replace(variable, '([0-9]{4})', ' ') str FROM test) tab
   CONNECT BY LEVEL <= LENGTH(str) - LENGTH(REPLACE(str, ' ')) + 1)
   SELECT listagg(str1, ' ') WITHIN GROUP (ORDER BY rn DESC) AS new_text
   INTO variable
   FROM str_tab;

  dbms_output.put_line('variable: ' || variable);
end;

CONNECT BY LEVEL 定义层次结构中父行和子行之间的关系。要理解它,请查看有关分层查询的文档中的分层查询示例:http://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm

尝试运行这个查询:

SELECT regexp_substr(str, '[^\[:space:]]+', 1, LEVEL) number_group,  LEVEL 
FROM (SELECT regexp_replace('363031393634816909877808647715885542447721', '([0-9]{4})', ' ') str FROM test)
CONNECT BY LEVEL <= LENGTH(str) - LENGTH(REPLACE(str, ' ')) + 1;

结果:

NUMBER_GROUP  LEVEL
3630          1
3139          2
3634          3
8169          4
0987          5
7808          6
6477          7
1588          8
5542          9
4477          10
21            11

LENGTH(str)是字符串的长度(加上spaces后),就是52。LENGTH(REPLACE(str, ' '))是加上spaces的长度删除,即 42。如果您取 (52-42)+1,您将得到 11,这是我们所有数字分组所需的行数。然后我们只需按 DESC 顺序获取该列表并使用 LISTAGG(使用 space 作为分隔符)重新组合字符串。