寻找函数分割字符串Oracle

寻找函数分割字符串Oracle,oracle,function,plsql,Oracle,Function,Plsql,我正在Oracle中寻找这样的函数 比如说 select xxx('orange,apple,banana,strawberry,Blueberry,tomato', ',' 3) from dual; 然后显示 orange,apple,banana, 数到3 及 显示 我希望这是有道理的 与您相比没有一个内置函数可以做到这一点。你可以接近正则表达式。但您也可以创建自己的函数,根据逗号确定所需段的起始和结束位置: create function foo(p_str varchar2, p_

我正在Oracle中寻找这样的函数

比如说

select xxx('orange,apple,banana,strawberry,Blueberry,tomato', ',' 3) from dual;
然后显示

orange,apple,banana,
数到3

显示

我希望这是有道理的


与您相比

没有一个内置函数可以做到这一点。你可以接近正则表达式。但您也可以创建自己的函数,根据逗号确定所需段的起始和结束位置:

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

您可以通过直接的substr和instr调用在普通SQL中实现这一点,但它会变得有点混乱

另一种方法是对原始字符串进行标记化,选择要保留的标记,然后将它们粘在一起:

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

没有一个内置函数可以做到这一点。你可以接近正则表达式。但您也可以创建自己的函数,根据逗号确定所需段的起始和结束位置:

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

您可以通过直接的substr和instr调用在普通SQL中实现这一点,但它会变得有点混乱

另一种方法是对原始字符串进行标记化,选择要保留的标记,然后将它们粘在一起:

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

第二个例子中的“2”代表什么?该调用是否应该从第二个分隔值开始并获取三个值;还是从第三个开始,得到第二个?结果也不匹配。听起来很有趣。到目前为止你试过什么?@AlexPoole so橙色'1',苹果'2',香蕉'3',草莓'4',蓝莓'5',番茄从2,2+3=5,到5,因此,香蕉,草莓,蓝莓,我希望这对你有意义。所以。。从第二个逗号后开始;在第一个查询中,隐式地在“第零个”逗号之后?是的,但这只是我编造的,我可以这样说。选择xxx‘橙色、苹果、香蕉、草莓、蓝莓、番茄’,’,,2,5显示香蕉、草莓、蓝莓第二个示例中的‘2’代表什么?该调用是否应该从第二个分隔值开始并获取三个值;还是从第三个开始,得到第二个?结果也不匹配。听起来很有趣。到目前为止你试过什么?@AlexPoole so橙色'1',苹果'2',香蕉'3',草莓'4',蓝莓'5',番茄从2,2+3=5,到5,因此,香蕉,草莓,蓝莓,我希望这对你有意义。所以。。从第二个逗号后开始;在第一个查询中,隐式地在“第零个”逗号之后?是的,但这只是我编的,我可以这样说。选择xxx‘橙色、苹果、香蕉、草莓、蓝莓、番茄’,’,,2,5显示香蕉、草莓、蓝莓因没有使用危险的’[^,]+'当分隔列表中存在空值时,将不会返回正确值的正则表达式@Gary_W-我正试图决定是否可以挤出一个链接到你的帖子,就像我每次使用你的方法时所做的那样;告诉过你我会把它记在书签里!;我现在也加在这里了。谢谢你,先生!当我想到那些糟糕的数据被返回到那里,而开发人员却不知道它正在发生时,我会感到害怕。@AlexPoole非常感谢!!!从昨天起,您就一直在帮助我,因为我没有使用危险的'[^,]+'正则表达式,当分隔列表中存在空值时,它将不会返回正确的值@Gary_W-我正试图决定是否可以挤出一个链接到你的帖子,就像我每次使用你的方法时所做的那样;告诉过你我会把它记在书签里!;我现在也加在这里了。谢谢你,先生!当我想到那些糟糕的数据被返回到那里,而开发人员却不知道它正在发生时,我会感到害怕。@AlexPoole非常感谢!!!从昨天起你一直在帮助我