将管道分隔的字符串解析为列?

Posted

技术标签:

【中文标题】将管道分隔的字符串解析为列?【英文标题】:Parsing pipe delimited string into columns? 【发布时间】:2010-05-31 07:38:22 【问题描述】:

我有一个带有管道分隔值的列,例如:

'23|12.1| 450|30|9|78|82.5|92.1|120|185|52|11'

我想解析此列以填充一个包含 12 个对应列的表:month1、month2、month3...month12。

因此,month1 的值为 23,month2 的值为 12.1,依此类推...

有没有办法通过循环或分隔符来解析它,而不必使用 substr 一次分隔一个值?

谢谢。

【问题讨论】:

How can fill a variable of my own created data type within Oracle PL/SQL?的可能重复 【参考方案1】:

你可以使用regexp_substr(10g+):

SQL> SELECT regexp_substr('23|12.1| 450|30|9|', '[^|]+', 1, 1) c1,
  2         regexp_substr('23|12.1| 450|30|9|', '[^|]+', 1, 2) c2,
  3         regexp_substr('23|12.1| 450|30|9|', '[^|]+', 1, 3) c3
  4    FROM dual;

C1 C2   C3
-- ---- ----
23 12.1  450

在 PL/SQL 中使用循环:

SQL> SET SERVEROUTPUT ON
SQL> DECLARE
  2     p_tsv  VARCHAR2(1000) := '23|12.1| 450|30|9|78|82.5|92.1|120|185|52|11';
  3     l_item VARCHAR2(100);
  4  BEGIN
  5     FOR i IN 1 .. length(p_tsv) - length(REPLACE(p_tsv, '|', '')) + 1 LOOP
  6        l_item := regexp_substr(p_tsv, '[^|]+', 1, i);
  7        dbms_output.put_line(l_item);
  8     END LOOP;
  9  END;
 10  /

23
12.1
450
30
9
78
82.5
92.1
120
185
52
11

PL/SQL procedure successfully completed

更新

只有有 12 列,我会直接编写查询而不使用循环,它会比动态 SQL 更高效且更易于维护(更不用说无限容易编写):

INSERT INTO your_table
   (ID, month1, month2, month3...)
   SELECT :p_id, 
          regexp_substr(:p_tsv, '[^|]+', 1, 1) c1, 
          regexp_substr(:p_tsv, '[^|]+', 1, 2) c2,
          regexp_substr(:p_tsv, '[^|]+', 1, 3) c3
          ...
     FROM dual;

【讨论】:

感谢文森特,您的帖子很有帮助,但这并不能解决整个问题。它不是解析问题的字符串,而是将它们分别插入到列中。就像可以在循环中添加什么来一次插入一列值一样?或者将它们全部插入到单独表中的记录中?我认为所有列都以索引(month1、month2、month3...)之类的东西结尾的事实应该有一种方法可以在循环中独立地访问和更新它们。谢谢 @DMS:在这种情况下我不会使用动态 SQL。出于性能原因和代码可维护性考虑,一条语句是可行的方法。【参考方案2】:

我不认为已经定义了一些东西。

orafaq 的实现很少,我也发现了this。

【讨论】:

【参考方案3】:

我有 99 个问题 所以我使用了正则表达式 现在我有100个问题 哈哈哈哈哈哈 只需将分隔符连接到字符串的开头和结尾

纯sql解决方案:

set define on
undefine string
undefine delim
undefine nth
accept string prompt 'Enter the string: '
accept delim prompt 'Enter the delimiter: '
accept nth prompt 'Enter nth: '
select '&&string' as string,
       '&&delim' as delimiter, 
        &&nth||decode(&&nth,1,'st',2,'nd',3,'rd','th') as nth,
 substr('&&delim'||'&&string'||'&delim',
        instr('&&delim'||'&&string'||'&&delim', '&&delim', 1, &&nth ) + length('&&delim'),
        instr('&&delim'||'&&string'||'&&delim', '&&delim', 1, &&nth + 1 ) - instr('&&delim'||'&&string'||'&&delim', '&&delim', 1, &&nth ) - length('&&delim')
       ) as val from dual

/

【讨论】:

以上是关于将管道分隔的字符串解析为列?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Oracle SQL 将可变长度分隔字符串拆分为列

如何将逗号分隔的值拆分为列

将字符串表达式解析为列

在 PySpark 中将字符串常量添加为列时未解析的引用点亮

使用管道连字符管道将数据加载到 Pig |-|分隔符

Google BigQuery SQL:将多级 JSON (list +json+list+json) 解析为列