没有一个内置函数可以做到这一点。你可以接近正则表达式。但您也可以创建自己的函数来根据逗号识别所需片段的开始和结束位置:
create function foo(p_str varchar2, p_delimiter varchar2,
p_occurrences number, p_position number default 0)
return varchar2 is
l_start pls_integer;
l_end pls_integer;
l_length pls_integer;
l_result varchar2(4000);
begin
l_start := case when p_position = 0 then 1
else instr(p_str, p_delimiter, 1, p_position) + 1 end;
l_end := instr(p_str, p_delimiter, l_start, p_occurrences);
l_length := case when l_end = 0 then length(p_str) - l_start + 1
else l_end - l_start end;
l_result := substr(p_str, l_start, l_length);
return l_result;
end;
/
然后,当您同时提供这两个参数时,交换示例中的参数(只是为了让 position 的默认值像这样工作):
select foo('orange,apple,banana,strawberry,Blueberry,tomato', ',', 1) from dual;
orange
select foo('orange,apple,banana,strawberry,Blueberry,tomato', ',', 3) from dual;
orange,apple,banana
select foo('orange,apple,banana,strawberry,Blueberry,tomato', ',', 3, 2) from dual;
banana,strawberry,Blueberry
select foo('orange,apple,banana,strawberry,Blueberry,tomato', ',', 3, 5) from dual;
tomato
如果您要求的次数多于实际次数,则它只返回存在的次数(即,尽管要求 3 个元素,但在最后一次调用中只返回“番茄”)。如果您的起始位置高于逗号数,则返回原始字符串,但您可以根据需要修改它以返回 null。
您可以在纯 SQL 中直接调用 substr 和 instr 来执行此操作,但它会有点混乱。
另一种方法是对原始字符串 (allowing for null elements) 进行标记,选择要保留的标记,然后将它们粘在一起:
select listagg(token, ',') within group (order by position) as result
from (
select level as position,
regexp_substr('orange,apple,banana,strawberry,Blueberry,tomato',
'(.*?)(,|$)', 1, level, null, 1) as token
from dual
connect by level <
regexp_count('orange,apple,banana,strawberry,Blueberry,tomato', '(.*?)(,|$)')
)
where position between 3 and 5;
banana,strawberry,Blueberry