2016-04-22 63 views
0

我必须将列拆分为多行。该列存储字符串,并且我们必须根据'/n'SQL基于分隔符将字段(字符串)拆分为多行的正则表达式'/ n'

分割分隔符。写了下面的查询。但无法指定^[/n]。字符串中的另一个'n'也被删除。请帮忙解析,您需要使用类字符串

WITH sample AS 
(SELECT 101 AS id, 
     'Name' test, 
     '3243243242342342/n12131212312/n123131232/n' as attribute_1, 
     'test value/nneenu not/nhoney' as attribute_2 
    FROM DUAL 
) 
-- end of sample data 
SELECT id, 
     test, 
     regexp_substr(attribute_1,'[^/n]+', 1, column_value), 
     regexp_substr(attribute_2,'[^/]+', 1, column_value) 
    FROM sample, 
     TABLE(
     CAST(
      MULTISET(SELECT LEVEL 
         FROM dual 
        CONNECT BY LEVEL <= LENGTH(attribute_1) - LENGTH(replace(attribute_1, '/n')) + 1 
        ) AS sys.OdciNumberList 
     ) 
     ) 
WHERE regexp_substr(attribute_1,'[^/n]+', 1, column_value) IS NOT NULL 
/
+1

你需要拆分字符串'/ n'还是你的意思是新行? – Aleksej

+0

嗨,我想你需要使用[[:cntrl:]]类 – Thomas

+0

和'[^/n] +'也没有语法好, – Thomas

回答

0

[:CNTRL:] 和 '[^/N] +' 在语法上不不太妙。

转义字符是“\”和,你需要使用()来代替,如果你想忽略CR不能使用[]“包装”特殊字符(即分组)

(例如” \ N'),用[^ [:CNTRL:]]在REGEXP_SUBSTR仲丁基PARAM

更多的帮助:http://psoug.org/snippet/Regular-Expressions--Regexp-Cheat-Sheet_856.htm

+0

Nitpicking:'\ n'代表'LF',而不是'CR' (这将是'\ r')。来源:其中包括你的......;) – collapsar

0

假设

/n应该表示\n以匹配换行符(严格地说[Posix]说LF字符(十六进制x0a))。

如果这个假设是错误的,请使用(^|/n)(([^/]|/+[^n])+)作为您的正则表达式,并使用regexp_substr(attribute_1,'(^|/n)(([^/]|/+[^n])+)', 1, column_value, '', 2)提取感兴趣的部分。

解决方案

不能字符类中指定的转义语法控制字符。使用posix字符类[:cntrl:]作品但受到其他角色的影响;出于实用目的,TAB(#x09)可能是一个麻烦。

但是,你可以指定一个正则表达式字符类的所有字符组成的文字模式字符串和调用到chr功能:

-- ... 
    '3243243242342342'||chr(13)||chr(10)||'12131212312'||chr(13)||chr(10)||'123131232'||chr(13)||chr(10) as attribute_1, 
    'test value'||chr(13)||chr(10)||'neenu not'||chr(13)||chr(10)||'honey' as attribute_2 
    -- ... 
    regexp_substr(attribute_1,'[^'||chr(13)||chr(10)||']+', 1, column_value), 
    regexp_substr(attribute_2,'[^'||chr(13)||chr(10)||']+', 1, column_value) 
    -- ... 

你可能想在sqlplus检查出下面的测试查询(在CR/LFS是文字的一部分;复制到一个文本编辑器,检查CR/LFS将被保留,重新插入如果没有,滴在sqlplus结果):

select regexp_substr('adda 
yxcv','[^'||CHR(10)||CHR(13)||']+', 1, 2) from dual; 
select regexp_substr('ad'||CHR(9)||'da 
yxcv','[^[:cntrl:]]+', 1, 2) from dual; 
+0

虽然OP的测试数据实际上有'/ n',而不是'\ n'。我也很惊讶,但如果你认为这是OP的测试数据中的一个错误,你应该在你的答案中这样说。 – hvd

+0

@ hvd是的,你说得对 - 我默认这是'\ n'在数据和模式中拼写错误。将相应地修改答案。 – collapsar

0
with test as (select 'ABC' || chr(13) || 'DEF' || chr(13) || 'GHI' || chr(13) || 'JKL' || chr(13) || 'MNO' str from dual) 
select regexp_substr (str, '[^' || chr(13) || ']+', 1, rownum) split 
from test 
connect by level <= length (regexp_replace (str, '[^' || chr(13) || ']+')) + 1 
0

首选的方法是修复数据模型,因为以这种方式存储的数据不是最优的。无论如何,请使用更多的测试数据来尝试此版本。我调整了正则表达式的:

WITH sample AS 
(SELECT 101 AS id, 
     'Name' test, 
     '3243243242342342/n12131212312/n123131232/n' as attribute_1, 
     'test value/nneenu not/nhoney' as attribute_2 
    FROM DUAL 
) 
-- end of sample data 
SELECT id, 
     test, 
     regexp_substr(attribute_1,'(.*?)(/n|$)', 1, column_value, NULL, 1), 
     regexp_substr(attribute_2,'(.*?)(/n|$)', 1, column_value, NULL, 1) 
    FROM sample, 
     TABLE(
     CAST(
      MULTISET(SELECT LEVEL 
         FROM dual 
        --CONNECT BY LEVEL <= LENGTH(attribute_1) - LENGTH(replace(attribute_1, '/n')) + 1 
         -- Counts substrings ending with the delimiter. 
         CONNECT BY LEVEL <= REGEXP_COUNT(attribute_1, '.*?/n')      
        ) AS sys.OdciNumberList 
     ) 
     ) 
WHERE regexp_substr(attribute_1,'(.*?)(/n|$)', 1, column_value, NULL, 1) IS NOT NULL 
/
相关问题