【问题标题】:SQL Regular expression to split a column (string) to multiple rows based on delimiter '/n'SQL正则表达式根据分隔符'/n'将列(字符串)拆分为多行
【发布时间】:2016-04-22 04:34:23
【问题描述】:

我必须将一列拆分为多行。该列存储字符串,我们必须根据'/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
/

【问题讨论】:

  • 你需要拆分字符串'/n'还是你的意思是换行?
  • 嗨,我想你需要使用 [[:cntrl:]] 类
  • 和 '[^/n]+' 在语法上也不好,

标签: sql regex oracle


【解决方案1】:

你需要使用类 [[:cntrl:]] 并且 '[^/n]+' 在语法上也不好。

转义字符是 '\',不能使用 [] 来“包裹”特殊字符,需要使用 () 代替。(即分组)

如果您想忽略 CR (例如'\n'),请在 regexp_substr 的 sec 参数中使用 [^[:cntrl:]]

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

【讨论】:

  • 吹毛求疵:\n 代表 LF,而不是 CR(应该是 \r)。资料来源:除其他外,您的... ;)
【解决方案2】:

假设

/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;

【讨论】:

  • OP 的测试数据实际上有/n,而不是\n。我也对此感到非常惊讶,但如果您认为这是 OP 测试数据中的错误,您应该在回答中这样说。
  • @hvd 是的,你是对的 - 我默认这是 \n 在数据和模式中的拼写错误。将相应地修改答案。
【解决方案3】:
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

【讨论】:

    【解决方案4】:

    第一选择是修复数据模型,因为以这种方式存储的数据不是最优的。无论如何,用更多的测试数据试试这个版本。我调整了正则表达式:

    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
    /
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-11
      • 2012-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-22
      相关资源
      最近更新 更多