REGEXP捕获由一组分隔符分隔的值

时间:2017-11-20 08:07:00

标签: oracle regexp-substr

我的列值如下所示:[只是我创建的一个例子]

$('#AddInventory').on('click', function () { var data = $("#validated_form").serialize(); $.ajax({ data: data + '&AddInventory=1', type: "POST", url: "Product_DB.php", dataType: 'json', success: function (data) { alert(data); } }); });

它可以包含0个或更多数据块...我创建了以下查询来拆分块

{BASICINFOxxxFyyy100x} {CONTACTxxx12345yyy20202x}

但是我想进一步将输出分成3列,如下所示:

with x as
 (select 
 '{BASICINFOxxxFyyy100x}{CONTACTxxx12345yyy20202x}' a from dual)
 select REGEXP_SUBSTR(a,'({.*?x})',1,rownum,null,1)
 from x
 connect by rownum <= REGEXP_COUNT(a,'x}')

分隔符始终是标准的。我没能创建一个漂亮的查询,它给了我想要的输出。

提前致谢。

3 个答案:

答案 0 :(得分:1)

SQL> with x as
  2   (select  '{BASICINFOxxxFyyy100x}{CONTACTxxx12345yyy20202x}' a from dual
  3   ),
  4  y as (
  5   select REGEXP_SUBSTR(a,'({.*?x})',1,rownum,null,1) c1
  6   from x
  7   connect by rownum <= REGEXP_COUNT(a,'x}')
  8  )
  9  select
 10    substr(c1,2,instr(c1,'xxx')-2) z1,
 11    substr(c1,instr(c1,'xxx')+3,instr(c1,'yyy')-instr(c1,'xxx')-3) z2,
 12    rtrim(substr(c1,instr(c1,'yyy')+3),'x}') z3
 13  from y;

Z1              Z2              Z3
--------------- --------------- ---------------
BASICINFO       F               100
CONTACT         12345           20202

答案 1 :(得分:1)

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE your_table ( str ) AS
SELECT '{BASICINFOxxxFyyy100x}{CONTACTxxx12345yyy20202x}' from dual
/

查询1

select REGEXP_SUBSTR(
         t.str,
         '\{([^}]*?)xxx([^}]*?)yyy([^}]*?)x\}',
         1,
         l.COLUMN_VALUE,
         NULL,
         1
       ) AS col1,
       REGEXP_SUBSTR(
         str,
         '\{([^}]*?)xxx([^}]*?)yyy([^}]*?)x\}',
         1,
         l.COLUMN_VALUE,
         NULL,
         2
       ) AS col2,
       REGEXP_SUBSTR(
         str,
         '\{([^}]*?)xxx([^}]*?)yyy([^}]*?)x\}',
         1,
         l.COLUMN_VALUE,
         NULL,
         3
       ) AS col3
FROM   your_table t
       CROSS JOIN
       TABLE(
         CAST(
           MULTISET(
             SELECT LEVEL
             FROM   DUAL
             CONNECT BY LEVEL <= REGEXP_COUNT( t.str,'\{([^}]*?)xxx([^}]*?)yyy([^}]*?)x\}')
           ) AS SYS.ODCINUMBERLIST
         )
       ) l

<强> Results

|      COL1 |  COL2 |  COL3 |
|-----------|-------|-------|
| BASICINFO |     F |   100 |
|   CONTACT | 12345 | 20202 |

注意:

您的查询:

select REGEXP_SUBSTR(a,'({.*?x})',1,rownum,null,1)
from x
connect by rownum <= REGEXP_COUNT(a,'x}')

当您有多行输入时无效 - 在CONNECT BY子句中,分层查询没有任何限制它将Row1-Level2连接到Row1-Level1或Row2-Level1所以它将它连接到随着层次结构的深度变得越来越大,它将创建输出行的指数级更多的重复副本。您可以使用黑客来阻止这种情况,但将行生成器放入相关的子查询中会更加高效,然后可以将CROSS JOIN放回到原始表中(它是相关的,因此它不会如果要使用分层查询,请加入错误的行。

最好还是修复数据结构,这样就不会在分隔的字符串中存储多个值。

答案 2 :(得分:1)

这是另一种解决方案,它来自您离开的地方。您的查询已导致将行拆分为2行。下面将分为3列:

WITH x
     AS (SELECT '{BASICINFOxxxFyyy100x}{CONTACTxxx12345yyy20202x}' a
           FROM DUAL),
-- Your query result here
     tbl
     AS (    SELECT REGEXP_SUBSTR (a,
                                   '({.*?x})',
                                   1,
                                   ROWNUM,
                                   NULL,
                                   1)
                       Col
               FROM x
         CONNECT BY ROWNUM <= REGEXP_COUNT (a, 'x}'))
--- Actual Query
SELECT col,
       REGEXP_SUBSTR (col,
                      '(.*?{)([^x]+)',
                      1,
                      1,
                      '',
                      2)
          AS COL1,
       REGEXP_SUBSTR (REGEXP_SUBSTR (col,
                                     '(.*?)([^x]+)',
                                     1,
                                     2,
                                     '',
                                     2),
                      '[^y]+',
                      1,
                      1)
          AS COL2,
       REGEXP_SUBSTR (REGEXP_SUBSTR (col,
                                     '[^y]+x',
                                     1,
                                     2),
                      '[^x]+',
                      1,
                      1)
          AS COL3
  FROM tbl;

输出:

SQL> /

COL                                              COL1                                             COL2                                             COL3
------------------------------------------------ ------------------------------------------------ ------------------------------------------------ ------------------------------------------------
{BASICINFOxxxFyyy100x}                           BASICINFO                                        F                                                100
{CONTACTxxx12345yyy20202x}                       CONTACT                                          12345                                            20202