【问题标题】:How to loop over tokens from a string in Oracle?如何从 Oracle 中的字符串中循环标记?
【发布时间】:2020-12-03 15:25:36
【问题描述】:

假设我有一个字符串 - '9999,34244324324\n88888,131321323\n77777,8787223'

我希望将由\n 分隔的每一对中的每个逗号分隔数字插入到表格的两列中。

例如,如下所示:

9999 |34244324324
88888|131321323
77777|8787223

使用 REGEXP_SUBSTR,我可以将这些对组合在一起:

REGEXP_SUBSTR(str, '((\d+),(\d+)\n?)',1,i, null, j)

其中i 找到num,num 匹配项,j 是第一个或第二个数字的 1 或 2。

我可以想象循环这个 i 次,我可以从 REGXP_COUNT 得到,但这似乎重复同样的事情 n 次。实现这一目标的正确方法是什么?

很长一段时间后我正在做数据库脚本,所以虽然我之前做过,但我不记得确切了。所以我需要这方面的建议。

【问题讨论】:

    标签: sql regex oracle plsql oracle11g


    【解决方案1】:
    1. 以“\n”作为分隔符将整个字符串分割成行:
    select *
    from  xmltable(
          'tokenize(., "\\n")'
          passing '9999,34244324324\n88888,131321323\n77777,8787223' 
          columns
             s varchar2(100) path '.'
          )
    

    结果:

    S
    ---------------------
    9999,34244324324
    88888,131321323
    77777,8787223
    
    1. 用“,”作为分隔符将每一行拆分为子字符串: 2.1 使用regexp_substr:
    select 
      s,
      regexp_substr(s,'^([^,]*),([^,]*)',1,1,'',1)  s1,
      regexp_substr(s,'^([^,]*),([^,]*)',1,1,'',2)  s2
    from  xmltable(
          'tokenize(., "\\n")'
          passing '9999,34244324324\n88888,131321323\n77777,8787223' 
          columns
             s varchar2(100) path '.'
          )
    

    结果:

    S                    S1           S2
    -------------------- ------------ ------------
    9999,34244324324     9999         34244324324
    88888,131321323      88888        131321323
    77777,8787223        77777        8787223
    

    或 2.2 使用相同的 xmltable:

    select *
    from  xmltable(
          'for $r in tokenize(., "\\n")
             return element R {
                attribute s1 {tokenize($r, ",")[1]}, 
                attribute s2 {tokenize($r, ",")[2]}
             }'
          passing '9999,34244324324\n88888,131321323\n77777,8787223' 
          columns
             s1 varchar2(10) path '@s1',
             s2 varchar2(10) path '@s2'
          )
    

    【讨论】:

      【解决方案2】:

      这是一个纯粹的基于 regexp_substr 的解决方案。 “d”子查询纯粹是您的数据。 Oracle 不能很好地理解 \n,因此 chr(10) 会处理这个问题。行子查询将您的数据按换行符拆分为行。最后一个查询以逗号分隔字符串。您可以通过添加额外的 regexp_substr 实例并增加最后一个(位置)参数来扩展两列逗号分隔的数据。

      WITH d AS
       (SELECT REPLACE('9999,34244324324\n88888,131321323\n77777,8787223',
                       '\n',
                       chr(10)) AS ata
          FROM dual),
      lines AS
       (SELECT regexp_substr(d.ata,
                             '[^' || chr(10) || ']+',
                             1,
                             LEVEL) AS line
          FROM d
        CONNECT BY regexp_substr(d.ata,
                                 '[^' || chr(10) || ']+',
                                 1,
                                 LEVEL) IS NOT NULL)
      SELECT l.line,
             regexp_substr(l.line,
                           '[^,]+',
                           1,
                           1) AS c1,
             regexp_substr(l.line,
                           '[^,]+',
                           1,
                           2) AS c2
        FROM lines l;
      

      生产:

      line                c1      c2
      ----------------    -----   -----------
      9999,34244324324    9999    34244324324
      88888,131321323     88888   131321323
      77777,8787223       77777   8787223
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-07
        • 2020-11-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多