在 Oracle 中使用 Regex_substr 到 select 字符串,直到最后一次出现的 space 在 \n 个字符长度内
Using Regex_substr in Oracle to select string up to the last occurence of a space within \n characters length
我们遇到一个问题,我们的 Oracle 数据库中的列的字符长度比另一个系统中的字段长。
因此,我尝试将 case 语句与 substr 一起使用,以拆分长度超过 40 个字符的字符串。到目前为止,我的案例陈述做了我希望他们做的事情,因为它将字符串的前 40 个字符留在 column_a 中,然后将字符串的其余部分放在 column_b 中。
但是,我遇到的问题是,仅使用 substr,字符串会在单词中途被拆分。
所以我想知道是否有人知道我可以与 regex_substr 一起使用的几个正则表达式 -
- select 40 个字符以内的最后一个 space 字符串 - 对于
column_a
- select 最后一个 space 之后的字符串,在 40 个字符内 - 对于
column_b
这些是我到目前为止对 substr 的案例陈述:
CASE WHEN Length(column_a) > 10 THEN SubStr(column_a, 0, 40) END AS column_a,
CASE WHEN Length(column_a) > 40 THEN SubStr(addressnum, 41) END AS column_b
我完全不熟悉正则表达式,因此非常感谢任何帮助!
我已经用 instr/substr 解决了:
select substr(column_a,1,instr(substr(column_a,1,40), ' ', -1 )) column1,
substr(column_a,instr(substr(column_a,1,40), ' ', -1 )+1, 40) column2
from table1
今天在 OTN 上发布了一个非常相似的问题。 https://community.oracle.com/message/13928697#13928697
我发布了一个通用的解决方案,它也将涵盖这里提出的问题。以后有类似的需求说不定能派上用场
对于这里发布的问题,row_lengths
table 将只有一行,r_id = 1
和 r_len = 40
。出于演示目的,我在下方显示了与我在 OTN 上使用的不同的 input_strings
。
设置:
create table input_strings (str_id number, txt varchar2(500));
insert into input_strings values (1,
'One Hundred Sixty-Nine Thousand Eight Hundred Seventy-Four Dollars And Nine Cents');
insert into input_strings values (2, null);
insert into input_strings values (3, 'Mathguy rules');
create table row_lengths (r_id number, r_len number);
insert into row_lengths values (1, 40);
commit;
select * from input_strings;
STR_ID TXT
------- ---------------------------------------------------------------------------------
1 One Hundred Sixty-Nine Thousand Eight Hundred Seventy-Four Dollars And Nine Cents
2
3 Mathguy rules
3 rows selected
select * from row_lengths;
R_ID R_LEN
------- ----------
1 40
1 row selected.
查询和输出:(注意:我包括令牌长度以验证第一个令牌不超过 40 个字符。如果第二个令牌可以更多,OP 没有回答超过 40 个字符;如果不能,可以将行添加到 row_lengths
table,也许每一行都添加 r_len = 40
。)
with
r ( r_id, r_len ) as (
select r_id , r_len from row_lengths union all
select max(r_id) + 1, 4000 from row_lengths union all
select max(r_id) + 2, null from row_lengths
),
b (str_id, str, r_id, token, prev_pos, new_pos) as (
select str_id, txt || ' ', -1, null, null, 0
from input_strings
union all
select b.str_id, b.str, b.r_id + 1,
substr(str, prev_pos + 1, new_pos - prev_pos - 1),
b.new_pos,
new_pos + instr(substr(b.str, b.new_pos + 1, r.r_len + 1) , ' ', -1)
from b join r
on b.r_id + 2 = r.r_id
)
select str_id, r_id, token, nvl(length(token), 0) as len
from b
where r_id > 0
order by str_id, r_id;
STR_ID R_ID TOKEN LEN
------- ------- ------------------------------------------------ -------
1 1 One Hundred Sixty-Nine Thousand Eight 37
1 2 Hundred Seventy-Four Dollars And Nine Cents 43
2 1 0
2 2 0
3 1 Mathguy rules 13
3 2 0
6 rows selected.
我们遇到一个问题,我们的 Oracle 数据库中的列的字符长度比另一个系统中的字段长。
因此,我尝试将 case 语句与 substr 一起使用,以拆分长度超过 40 个字符的字符串。到目前为止,我的案例陈述做了我希望他们做的事情,因为它将字符串的前 40 个字符留在 column_a 中,然后将字符串的其余部分放在 column_b 中。
但是,我遇到的问题是,仅使用 substr,字符串会在单词中途被拆分。
所以我想知道是否有人知道我可以与 regex_substr 一起使用的几个正则表达式 -
- select 40 个字符以内的最后一个 space 字符串 - 对于 column_a
- select 最后一个 space 之后的字符串,在 40 个字符内 - 对于 column_b
这些是我到目前为止对 substr 的案例陈述:
CASE WHEN Length(column_a) > 10 THEN SubStr(column_a, 0, 40) END AS column_a,
CASE WHEN Length(column_a) > 40 THEN SubStr(addressnum, 41) END AS column_b
我完全不熟悉正则表达式,因此非常感谢任何帮助!
我已经用 instr/substr 解决了:
select substr(column_a,1,instr(substr(column_a,1,40), ' ', -1 )) column1,
substr(column_a,instr(substr(column_a,1,40), ' ', -1 )+1, 40) column2
from table1
今天在 OTN 上发布了一个非常相似的问题。 https://community.oracle.com/message/13928697#13928697
我发布了一个通用的解决方案,它也将涵盖这里提出的问题。以后有类似的需求说不定能派上用场
对于这里发布的问题,row_lengths
table 将只有一行,r_id = 1
和 r_len = 40
。出于演示目的,我在下方显示了与我在 OTN 上使用的不同的 input_strings
。
设置:
create table input_strings (str_id number, txt varchar2(500));
insert into input_strings values (1,
'One Hundred Sixty-Nine Thousand Eight Hundred Seventy-Four Dollars And Nine Cents');
insert into input_strings values (2, null);
insert into input_strings values (3, 'Mathguy rules');
create table row_lengths (r_id number, r_len number);
insert into row_lengths values (1, 40);
commit;
select * from input_strings;
STR_ID TXT
------- ---------------------------------------------------------------------------------
1 One Hundred Sixty-Nine Thousand Eight Hundred Seventy-Four Dollars And Nine Cents
2
3 Mathguy rules
3 rows selected
select * from row_lengths;
R_ID R_LEN
------- ----------
1 40
1 row selected.
查询和输出:(注意:我包括令牌长度以验证第一个令牌不超过 40 个字符。如果第二个令牌可以更多,OP 没有回答超过 40 个字符;如果不能,可以将行添加到 row_lengths
table,也许每一行都添加 r_len = 40
。)
with
r ( r_id, r_len ) as (
select r_id , r_len from row_lengths union all
select max(r_id) + 1, 4000 from row_lengths union all
select max(r_id) + 2, null from row_lengths
),
b (str_id, str, r_id, token, prev_pos, new_pos) as (
select str_id, txt || ' ', -1, null, null, 0
from input_strings
union all
select b.str_id, b.str, b.r_id + 1,
substr(str, prev_pos + 1, new_pos - prev_pos - 1),
b.new_pos,
new_pos + instr(substr(b.str, b.new_pos + 1, r.r_len + 1) , ' ', -1)
from b join r
on b.r_id + 2 = r.r_id
)
select str_id, r_id, token, nvl(length(token), 0) as len
from b
where r_id > 0
order by str_id, r_id;
STR_ID R_ID TOKEN LEN
------- ------- ------------------------------------------------ -------
1 1 One Hundred Sixty-Nine Thousand Eight 37
1 2 Hundred Seventy-Four Dollars And Nine Cents 43
2 1 0
2 2 0
3 1 Mathguy rules 13
3 2 0
6 rows selected.