如何从 Oracle 中的字符串中提取子链,从特定的已知模式开始
How to extract a subchain from a string in Oracle, starting with a specific known pattern
在下面的示例中,我需要提取所有以模式“B0D_”开头的单词,并将结果作为由所有找到的值分开的字符串组成通过一个没有空格的分号。来自 Oracle table.
的所有数据
INPUT : HP-003 [R8003 A - R8003 B] AND (**B0D_A5** AND DMW_11) OR (**B0D_C5** AND DMW_11) OR (B0E_003)
OUTPUT : B0D_A5;B0D_C5
我有点偏爱正则表达式。
提前致谢。
这是一个选项(第 1 行和第 2 行中的示例数据;您需要的查询从第 3 行开始)。它在分层查询中找到所有 B0D%
字符串,并使用 LISTAGG
.
连接它们
SQL> with test (id, col) as
2 (select 1, 'HP-003 [R8003 A - R8003 B] AND (B0D_A5 AND DMW_11) OR (B0D_C5 AND DMW_11) OR (B0E_003)' from dual
3 union all
4 select 2, 'ASX (SDR) AND (XAZ AND B0D_F23F)' from dual)
5 select id,
6 listagg(regexp_substr(col, 'B0D\w+', 1, column_value), ';')
7 within group (order by column_value) result
8 from test cross join table(cast(multiset(select level from dual
9 connect by level <= regexp_count(col, 'B0D')
10 ) as sys.odcinumberlist))
11 group by id
12 order by id;
ID RESULT
---------- ------------------------------
1 B0D_A5;B0D_C5
2 B0D_F23F
SQL>
单身regexp_replace
就够了
模式 (.*?)((B0D\w+)|$)
将第一组定义为 非贪婪 用于单词前的无趣字符。
第二组是(嵌套)搜索到的词或行尾。
regexp_replace
选择所有出现(第5个参数= 0)第三组(单词)并追加一个分号。
所以最后你必须 trim 结尾的分号。
带有一些额外测试数据的查询
with tab as (
select 'INPUT : HP-003 [R8003 A - R8003 B] AND (B0D_A5 AND DMW_11) OR (B0D_C5 AND DMW_11) OR (B0E_003)' col from dual union all
select 'INPUT : HP-003 [R8003 A - R8003 B] AND (B0D_A5 AND DMW_11) OR (B0D_C5 AND DMW_11) OR (B0E_003) B0D_A6' col from dual union all
select 'INPUT : HP-003 [R8003 A - R8003 B] AND (B0D_A5 AND DMW_11) OR (B0D_C5 AND DMW_11) OR (B0E_003) B0D_A6B0D_FIN' col from dual
)
select
rtrim(regexp_replace(col,'(.*?)((B0D\w+)|$)',';',1,0),';') b0d_lst
from tab
B0D_LST
---------
B0D_A5;B0D_C5
B0D_A5;B0D_C5;B0D_A6
B0D_A5;B0D_C5;B0D_A6B0D_FIN
在下面的示例中,我需要提取所有以模式“B0D_”开头的单词,并将结果作为由所有找到的值分开的字符串组成通过一个没有空格的分号。来自 Oracle table.
的所有数据INPUT : HP-003 [R8003 A - R8003 B] AND (**B0D_A5** AND DMW_11) OR (**B0D_C5** AND DMW_11) OR (B0E_003)
OUTPUT : B0D_A5;B0D_C5
我有点偏爱正则表达式。
提前致谢。
这是一个选项(第 1 行和第 2 行中的示例数据;您需要的查询从第 3 行开始)。它在分层查询中找到所有 B0D%
字符串,并使用 LISTAGG
.
SQL> with test (id, col) as
2 (select 1, 'HP-003 [R8003 A - R8003 B] AND (B0D_A5 AND DMW_11) OR (B0D_C5 AND DMW_11) OR (B0E_003)' from dual
3 union all
4 select 2, 'ASX (SDR) AND (XAZ AND B0D_F23F)' from dual)
5 select id,
6 listagg(regexp_substr(col, 'B0D\w+', 1, column_value), ';')
7 within group (order by column_value) result
8 from test cross join table(cast(multiset(select level from dual
9 connect by level <= regexp_count(col, 'B0D')
10 ) as sys.odcinumberlist))
11 group by id
12 order by id;
ID RESULT
---------- ------------------------------
1 B0D_A5;B0D_C5
2 B0D_F23F
SQL>
单身regexp_replace
就够了
模式 (.*?)((B0D\w+)|$)
将第一组定义为 非贪婪 用于单词前的无趣字符。
第二组是(嵌套)搜索到的词或行尾。
regexp_replace
选择所有出现(第5个参数= 0)第三组(单词)并追加一个分号。
所以最后你必须 trim 结尾的分号。
带有一些额外测试数据的查询
with tab as (
select 'INPUT : HP-003 [R8003 A - R8003 B] AND (B0D_A5 AND DMW_11) OR (B0D_C5 AND DMW_11) OR (B0E_003)' col from dual union all
select 'INPUT : HP-003 [R8003 A - R8003 B] AND (B0D_A5 AND DMW_11) OR (B0D_C5 AND DMW_11) OR (B0E_003) B0D_A6' col from dual union all
select 'INPUT : HP-003 [R8003 A - R8003 B] AND (B0D_A5 AND DMW_11) OR (B0D_C5 AND DMW_11) OR (B0E_003) B0D_A6B0D_FIN' col from dual
)
select
rtrim(regexp_replace(col,'(.*?)((B0D\w+)|$)',';',1,0),';') b0d_lst
from tab
B0D_LST
---------
B0D_A5;B0D_C5
B0D_A5;B0D_C5;B0D_A6
B0D_A5;B0D_C5;B0D_A6B0D_FIN