使用oracle按分隔符位置拆分字符串

Posted

技术标签:

【中文标题】使用oracle按分隔符位置拆分字符串【英文标题】:Split String by delimiter position using oracle 【发布时间】:2017-01-30 16:20:04 【问题描述】:

我在 oracle 表中有一个类似 ',,defoifcd,87765' 的字符串。意思是,前两个字符串是空的。所以我需要在 Oracle 中用逗号分隔字符串作为分隔符。我正在编写这个查询

SELECT  
REGEXP_SUBSTR (TEST_STRING, '[^,]+', 1, 1)    AS part_1,
REGEXP_SUBSTR (TEST_STRING, '[^,]+', 1, 2)    AS part_2,
REGEXP_SUBSTR (TEST_STRING, '[^,]+', 1, 3)    AS part_3,
REGEXP_SUBSTR (TEST_STRING, '[^,]+', 1, 4)    AS part_4
FROM ABCD
;

这里 ABCD 是我的表,TEST_STRING 是我的库。

但结果返回像

PART_1,  part_2,  part_3,  part_4
defoifcd,87765

但我想要这样的结果,

PART_1,  part_2,  part_3,  part_4
                  defoifcd, 87765

意味着我需要 part_3 和 part_4 列中的 'defoifcd' 和 '87765' 值,因为前两个字符串是空的,但根据我的查询,它在 part_1 和 part_2 列中是 comimg。

【问题讨论】:

Split comma separated values to columns in Oracle的可能重复 非常具体:不要检查接受的答案,而是检查 Gary 的答案:他正在解释和解决您当前的问题。 总是正好是四个部分吗? 并不总是四部分。 那么您将无法像这样排列列。除非您使用“动态 SQL”(这是一个不同的过程,并且通常不是最佳的),否则在查看数据之前必须提前知道输出列的数量。是否有预先已知的可用于查询的最大零件数?如果不是,您真的需要按列输出(而不是一列用于指定部件,另一列用于值)? 【参考方案1】:

如果你只有一个字符串并且你知道它总是正好有四个部分,你可以像这样拆分它,只使用标准的字符串函数(并避免使用更灵活但通常更慢的正则表达式)。

注意:此答案的后半部分涉及“部分”数量可变的字符串。

with inputs ( str ) as (
       select ',,defoifcd,87765' from dual
     )
-- end of TEST data; SQL query begins below (use your actual table and column names)
select substr(str, 1, instr(str, ',') - 1) as part_1,
       substr(str, instr(str, ',') + 1, 
              instr(str, ',', 1, 2) - instr(str, ',') - 1) as part_2,
       substr(str, instr(str, ',', 1, 2) + 1, 
              instr(str, ',', 1, 3) - instr(str, ',', 1, 2) - 1) as part_3,
       substr(str, instr(str, ',', -1) + 1) as part_4
from   inputs;

PART_1   PART_2   PART_3   PART_4
-------- -------- -------- --------
                  defoifcd 87765

1 row selected.

如果事先不知道零件的数量,最好以不同的格式获得输出(参见下面的输出)。如果需要在所有其他处理完成后将部分排列在列中 - 最好留给报告应用程序,而不是在 SQL 中完成。

with inputs ( id, str ) as (
       select 1, ',,defoifcd,87765' from dual union all
       select 2, ''                 from dual union all
       select 3, 'a, b, c'          from dual
     )
-- end of TEST data; SQL query begins below (use your actual table and column names)
select id, str, level as part_number,
       substr(aug_str, instr(aug_str, ',', 1, level) + 1,
              instr(aug_str, ',', 1, level + 1) - instr(aug_str, ',', 1, level) - 1) as val
from   ( select id, str, ',' || str || ',' as aug_str from inputs)
connect by level <= length(str) - length(translate(str, 'z,', 'z')) + 1
       and prior id = id
       and prior sys_guid() is not null
;

ID STR              PART_NUMBER VAL
-- ---------------- ----------- ----------
 1 ,,defoifcd,87765           1
 1 ,,defoifcd,87765           2
 1 ,,defoifcd,87765           3 defoifcd
 1 ,,defoifcd,87765           4 87765
 2                            1
 3 a, b, c                    1 a
 3 a, b, c                    2  b
 3 a, b, c                    3  c

8 rows selected.

【讨论】:

你的第一个例子正是我正在经历的;你的第二个例子很有创意;)

以上是关于使用oracle按分隔符位置拆分字符串的主要内容,如果未能解决你的问题,请参考以下文章

使用正则表达式在Oracle中按分隔符拆分字符串

使用 regexp_substr 在 Oracle 中按空格和字符拆分字符串作为分隔符

获取字符串,按分隔符拆分并插入到 Oracle 中的表过程 [重复]

SQL拆分逗号分隔的字符串

SQL拆分逗号分隔的字符串

在Oracle中将连字符分隔的字符串拆分为行