Vel*_*ity 1 sql oracle plsql regexp-substr
我在表中有一个字符串、clob 值,我需要将其拆分为列。源表查询:
Insert into disp_data(id,data) values(100,
'"Project title as per the outstanding Requirements","The values are not with respect to the requirement and analysis done by the team.
Also it is difficult to prepare a scenario notwithstanding the fact it is difficult. This user story is going to be slightly complex however it is up to the team","Active","Disabled","25 tonnes of fuel","www.examplesites.com/html.asp&net;","","","","","25"');
Run Code Online (Sandbox Code Playgroud)
在 clob 列值中也存在空格、空值和行间隙。所以当我尝试使用分割它时
select regexp_substr(data,'[^,]+',1,level) from disp_data
connect by regexp_substr(data,'[^,]+',1,level) is not null.
Run Code Online (Sandbox Code Playgroud)
问题是对于有行间隙的大文本,它会将其分成不同的行。我曾想过使用上面的结果集和数据透视表,但无法做到。
我需要将此数据作为列获取并推入目标表-push_data_temp。
select pid,col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11 from push_data_temp;
Run Code Online (Sandbox Code Playgroud)
clob 列有 11 个逗号分隔的值,需要将它们作为列推入此表中。整个过程需要通过 pl/sql 过程来完成。
任何帮助将非常感激。数据库是oracle 19c
您的正则表达式需要允许 null,即连续逗号(但希望您在任何引用的字符串中都没有逗号...)。如果您有多个源行,那么使用递归 CTE 进行分割会更容易:
with rcte (id, data, lvl, result) as (
select id, data, 1, regexp_substr(data, '(.*?)(,|$)', 1, 1, null, 1)
from disp_data
union all
select id, data, lvl + 1, regexp_substr(data, '(.*?)(,|$)', 1, lvl + 1, null, 1)
from rcte
where lvl <= regexp_count(data, ',')
)
select id, lvl, result
from rcte
order by id, lvl;
Run Code Online (Sandbox Code Playgroud)
然后,您可以将结果转入您想要的列:
with rcte (id, data, lvl, result) as (
select id, data, 1, regexp_substr(data, '(.*?)(,|$)', 1, 1, null, 1)
from disp_data
union all
select id, data, lvl + 1, regexp_substr(data, '(.*?)(,|$)', 1, lvl + 1, null, 1)
from rcte
where lvl <= regexp_count(data, ',')
)
select *
from (
select id, lvl, result
from rcte
)
pivot (max(result) as col for (lvl) in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
Run Code Online (Sandbox Code Playgroud)
您可以直接在插入语句中使用它:
insert into push_data_temp (pid,col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11)
with rcte (id, data, lvl, result) as (
select id, data, 1, regexp_substr(data, '(.*?)(,|$)', 1, 1, null, 1)
from disp_data
union all
select id, data, lvl + 1, regexp_substr(data, '(.*?)(,|$)', 1, lvl + 1, null, 1)
from rcte
where lvl <= regexp_count(data, ',')
)
select *
from (
select id, lvl, result
from rcte
)
pivot (max(result) as col for (lvl) in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
Run Code Online (Sandbox Code Playgroud)
不需要 PL/SQL,但如果您愿意,您仍然可以将其包装在过程中。
我必须采用 clob,它会因为数据类型不一致而引发错误
您需要将令牌转换为varchar2,这限制了它们的长度(4k 或 32k,具体取决于 Oracle 版本和设置):
with rcte (id, data, lvl, result) as (
select id, data, 1,
cast(regexp_substr(data, '(.*?)(,|$)', 1, 1, null, 1) as varchar2(4000))
from disp_data
union all
select id, data, lvl + 1,
cast(regexp_substr(data, '(.*?)(,|$)', 1, lvl + 1, null, 1) as varchar2(4000))
from rcte
where lvl <= regexp_count(data, ',')
)
...
Run Code Online (Sandbox Code Playgroud)
db<>摆弄CLOB (并删除了连接示例,因为它们破坏了它......)
当我尝试输入中间有逗号的文本时,它会不均匀地分割数据。
这就是为什么我说“希望您在任何引用的字符串中都没有逗号”。由于您没有任何真正空的元素 - 您有...","","...而不是...,,...- 您可以跳过对我认为的那些元素的关注,并使用不同的模式:
with rcte (id, data, lvl, result) as (
select id, data, 1,
cast(regexp_substr(data, '("[^"]*"|[^,]+)', 1, 1, null, 1) as varchar2(4000))
from disp_data
union all
select id, data, lvl + 1,
cast(regexp_substr(data, '("[^"]*"|[^,]+)', 1, lvl + 1, null, 1) as varchar2(4000))
from rcte
where lvl <= regexp_count(data, '("[^"]*"|[^,]+)')
)
...
Run Code Online (Sandbox Code Playgroud)
如果您确实必须处理 null 元素,那么它仍然是可能的,但需要更多工作。这也不会处理没有字符串的转义双引号。在某些时候,用 PL/SQL 编写自己的解析器会更容易;或者甚至将数据写入磁盘并将其作为外部表读回,它可以为您处理所有这些。
| 归档时间: |
|
| 查看次数: |
1348 次 |
| 最近记录: |