将分隔数据转换为Oracle中的行

时间:2018-01-30 12:10:59

标签: oracle

这里我有一个源表 来源表:

ID | Log
____________________
1  | Status : New 
   | Assignment : 1
   | Priority : Low
_____________________
2  | Status : In Progress

目标表:

ID | Key       | Value
____________________
1  | Status    | New 
1  | Assignment| 1
1  | Priority  | Low
2  | Status    | In Progress

请提出建议。 提前谢谢。

2 个答案:

答案 0 :(得分:1)

这样的事情应该有效。您似乎在必须删除的实际令牌周围有一些空格,因此我使用TRIM()函数。

WITH子句仅用于测试(不是您问题的SQL解决方案的一部分 - 在针对您的实际表和列进行测试之前将其删除)。

with
  source_table ( id, log ) as (
    select 1, 'Status : New 
               Assignment : 1
               Priority : Low'       from dual union all
    select 2, 'Status : In Progress' from dual
  )
select id,
       trim(regexp_substr(log, '(' || chr(10) || '|^)([^:]*):', 1, level, null, 2)) key,
       trim(regexp_substr(log, ':([^:]*)(' || chr(10) || '|$)', 1, level, null, 1)) value
from   source_table
connect by level <= regexp_count(log, ':')
       and prior id = id
       and prior sys_guid() is not null
;

ID  KEY           VALUE              
--  ------------  --------------
 1  Status        New           
 1  Assignment    1             
 1  Priority      Low           
 2  Status        In Progress   

答案 1 :(得分:0)

这是另一种选择; TEST代表您的样本数据。 INTER分割行(由CHR(10)分隔),而最终的SELECT使用简单的SUBSTR + INSTR组合。

SQL> WITH test (id, LOG)
  2       AS (SELECT 1,
  3                     'status: new'
  4                  || CHR (10)
  5                  || 'assignment: 1'
  6                  || CHR (10)
  7                  || 'priority: low'
  8             FROM DUAL
  9           UNION
 10           SELECT 2, 'status: in progress' FROM DUAL),
 11       inter
 12       AS (SELECT id,
 13                  REGEXP_SUBSTR (REPLACE (LOG, CHR (10), ';'),
 14                                 '[^;]+',
 15                                 1,
 16                                 COLUMN_VALUE)
 17                     LOG
 18             FROM test,
 19                  TABLE (
 20                     CAST (
 21                        MULTISET (
 22                               SELECT LEVEL
 23                                 FROM DUAL
 24                           CONNECT BY LEVEL <= REGEXP_COUNT (LOG, ':') + 1) AS SYS.odcinumberlist)))
 25    SELECT id,
 26           TRIM (SUBSTR (LOG, 1, INSTR (LOG, ':') - 1)) key,
 27           TRIM (SUBSTR (LOG, INSTR (LOG, ':') + 1, LENGTH (LOG))) VALUE
 28      FROM inter
 29     WHERE LOG IS NOT NULL
 30  ORDER BY id;

  ID KEY             VALUE
---- --------------- ---------------
   1 status          new
   1 assignment      1
   1 priority        low
   2 status          in progress

SQL>