将Varchar字段拆分为多行Oracle

时间:2018-06-27 15:20:57

标签: sql regex string oracle plsql

在Oracle中,我有一个表,我需要将其字段之一分成几行。问题是没有确切的分隔符,我只知道属性的值格式是什么。

NumberVarchar 团结

示例如下。

objectid    linkvalue
    1       1V 2E 3T/B
    2       3C+1E. 3V
    3       5V.4PH
    4       V H
    5       V H 8V

我需要输出类似于以下内容将其插入到另一个表中:

objectid    linkvalue
    1          1V
    1          2E
    1          3T/B
    2          3C
    2          1E
    2          3V
    3          5V
    3          4PH
    4          V H
    5          V H
    5          8V

任何想法或建议该怎么做?预先非常感谢

3 个答案:

答案 0 :(得分:2)

这是另一种方式:

with tbl(objectid, linkvalue) as (
  select 1, '1V 2E 3T/B' from dual union all
  select 2, '3C+1E. 3V' from dual union all
  select 3, '5V.4PH' from dual
)
select objectid,
       regexp_substr(linkvalue, '(.*?)([ +.]+|$)', 1, level, NULL, 1)
from tbl
connect by level <= regexp_count(linkvalue, '[ +.]+') + 1
and prior objectid = objectid
and prior sys_guid() is not null;


OBJECTID    REGEXP_SUBSTR(LINKVALUE,'(.*?)([ +.]+|$)',1,LEVEL,NULL,1)
--------    ----------------------------------------------------------
1           1V
1           2E
1           3T/B
2           3C
2           1E
2           3V
3           5V
3           4PH

编辑:添加了没有分隔符的情况。通过以在大写字母和数字之间添加空格。当然有点脏,但我不告诉你是否不会。

Edit2:允许使用由一个或多个定界符分隔的多个单个大写字母组成的值。正则表达式越来越难看。

-- Set up data set
with tbl(objectid, linkvalue) as (
  select 1, '1V 2E 3T/B' from dual union all
  select 2, '3C+1E. 3V' from dual union all
  select 3, '5V.4PH' from dual union all
  select 4, '4H6C' from dual union all
  select 5, 'C E O 8V' from dual union all
  select 6, 'V H' from dual union all
  select 7, '9X X Y Z' from dual
),
-- Add a delimiter where missing
tbl1(objectid, linkvalue) as (
  select objectid,
         regexp_replace(linkvalue, '([A-Z])([0-9])', '\1 \2')
  from tbl
)
select objectid,
       regexp_substr(linkvalue, '(([A-Z][ +.]?)+|.*?)([ +.]+|$)', 1, level, NULL, 1)
from tbl1
connect by regexp_substr(linkvalue, '(([A-Z][ +.]?)+|.*?)([ +.]+|$)', 1, level) is not null
and prior objectid = objectid
and prior sys_guid() is not null;

答案 1 :(得分:1)

如果分隔符可以是.+,则此查询有效:

select distinct objectid,regexp_substr(linkvalue,'[^+|.| ]+', 1, level) txt
from (          select 1   objectid,  '1V 2E 3T/B'   linkvalue from dual 
       union all select 2 ,            '3C+1E. 3V'              from dual
       union all select 3,             '5V.4PH'                 from dual)
connect by regexp_substr(linkvalue, '[^+|.| ]+', 1, level) is not null
order by 1

答案 2 :(得分:-3)

将所有换行符替换为普通的换行符(在下面的情况下,我使用空格)。然后进行交叉联接并过滤掉所有空白值。

declare @data table(id int, codes varchar(50))

insert into @data values
(1, '1V 2E 3T/B'),
(2, '3C+1E. 3V'),
(3, '5V4PH')

select id, value
from (select id, replace(replace(replace(codes, 'V', 'V '), '+', ' '), '.', ' ') [codes] 
      from @data) d
cross apply string_split(d.codes, ' ')
where value <> ''