这个oracle函数的字符拼接怎么做

CalvinR 2015-07-29 11:20:05
需求:函数传入一个字符串参数 例如 123-456

将这个字符串123-456拆成两个值 123 456,在通过两个值分别查出数据(例如 张三 李四),拼接成 张三-李四

我写的函数是这样
分割字符的函数[这个网上找的 没问题]

CREATE OR REPLACE TYPE str_split IS TABLE OF VARCHAR2 (4000);
CREATE OR REPLACE FUNCTION splitstr(p_string IN VARCHAR2, p_delimiter IN VARCHAR2)
RETURN str_split
PIPELINED
AS
v_length NUMBER := LENGTH(p_string);
v_start NUMBER := 1;
v_index NUMBER;
BEGIN
WHILE(v_start <= v_length)
LOOP
v_index := INSTR(p_string, p_delimiter, v_start);

IF v_index = 0
THEN
PIPE ROW(SUBSTR(p_string, v_start));
v_start := v_length + 1;
ELSE
PIPE ROW(SUBSTR(p_string, v_start, v_index - v_start));
v_start := v_index + 1;
END IF;
END LOOP;

RETURN;
END splitstr;


--使用方法--
select * from table(splitstr('16021-16022','-'));

--执行出的结果

COLUMN_VALUE
16021
16022


这个是我自己写的函数

CREATE OR REPLACE FUNCTION fn_GetDead (v_deadId varchar2)
return varchar2
is

v_deadString varchar2(100);
cursor c_deadIdSpilt --设置一个分割字符串游标--
is
select * from table(splitstr(''||v_deadId||'','-'));
c_row c_deadIdSpilt%rowtype;

begin

if instr(v_deadId,'-') > 0 then ---判读变量中是否含有"-"字符,如果有,则循环遍历这个字符,取出亡人姓名
open c_deadIdSpilt; --打开游标--
loop
fetch c_deadIdSpilt into c_row;

SELECT wrxm into v_deadString FROM wrxxb WHERE id=C_ROW.COLUMN_VALUE;

v_deadString:=v_deadString||'-';
return v_deadString;
end loop;
v_deadString := substr(v_deadString, 1, LENGTH(v_deadString) - 1);
close c_deadIdSpilt;

else

SELECT wrxm INTO v_deadString FROM wrxxb WHERE id=''||v_deadId||'';

return v_deadString;
end if;

--异常处理--
exception

when others then dbms_output.put_line('error');
return -1;
end fn_GetDead;
/

--调用--
SELECT fn_GetDead('16021-16022') FROM dual;

我执行出的结果
FN_GETDEAD('16021-16022')
齐同元-



我不知道哪里出错了,请大家帮忙看看哪里出错了?

只能发100分的帖子
...全文
482 14 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
CalvinR 2015-08-04
  • 打赏
  • 举报
回复
引用 11 楼 wildwave 的回复:
return早了。不管有多少行,都会在第一行以后跳出。另外赋值上也不太对
CREATE OR REPLACE FUNCTION  fn_GetDead (v_deadId varchar2)
return varchar2
is
 
v_deadString varchar2(100);
v_deadString_all VARCHAR2(4000);
cursor c_deadIdSpilt  --设置一个分割字符串游标--
 is
select *  from table(splitstr(''||v_deadId||'','-'));
c_row c_deadIdSpilt%rowtype;
 
begin  
   
 if  instr(v_deadId,'-') > 0 then  ---判读变量中是否含有"-"字符,如果有,则循环遍历这个字符,取出亡人姓名
  open c_deadIdSpilt;              --打开游标--
  loop
    fetch c_deadIdSpilt into c_row;
    EXIT WHEN c_deadIdSpilt%NOTFOUND;
      SELECT wrxm into v_deadString FROM wrxxb WHERE id=C_ROW.COLUMN_VALUE;
       
       v_deadString_all:=v_deadString_all||'-'||v_deadString;       
      
  end loop;
 
 close c_deadIdSpilt;

  return ltrim(v_deadString_all,'-');
 else
    
  SELECT wrxm INTO v_deadString FROM wrxxb WHERE id=''||v_deadId||'';
 
  return v_deadString;
 end if;
 
--异常处理--
exception
 
  when others then dbms_output.put_line('error');
  return -1;
end fn_GetDead;
/
谢谢版主 按你的方法解决了
CalvinR 2015-08-04
  • 打赏
  • 举报
回复
引用 12 楼 hanfujie1234 的回复:
楼主哇,你的loop里面有问题,你用v_deadString来作为输出结果,但是以下语句每次都把v_deadString的值情况了: SELECT wrxm into v_deadString FROM wrxxb WHERE id=C_ROW.COLUMN_VALUE; 加入第一次取到的是张三,则: v_deadString=张三- 第二次去取李四,则 v_deadString=李四- 所以无论你传几个id进去最后只能取到最后一个id对应的人名 应该再定义一个参数来接受每次loop里面取到的人名: SELECT wrxm into v_name FROM wrxxb WHERE id=C_ROW.COLUMN_VALUE; 然后拼接: v_deadString := v_deadString||v_name || '-';
这个没问题吧 不是这里的问题
滇中倦客 2015-07-31
  • 打赏
  • 举报
回复
楼主哇,你的loop里面有问题,你用v_deadString来作为输出结果,但是以下语句每次都把v_deadString的值情况了:
SELECT wrxm into v_deadString FROM wrxxb WHERE id=C_ROW.COLUMN_VALUE;
加入第一次取到的是张三,则:
v_deadString=张三-
第二次去取李四,则
v_deadString=李四-
所以无论你传几个id进去最后只能取到最后一个id对应的人名
应该再定义一个参数来接受每次loop里面取到的人名:
SELECT wrxm into v_name FROM wrxxb WHERE id=C_ROW.COLUMN_VALUE;
然后拼接:
v_deadString := v_deadString||v_name || '-';
mayanzs 2015-07-30
  • 打赏
  • 举报
回复

--对多个“-”可以用 regexp_count() 函数
with table1 as
(
select 123 col1, '张三' col2 from dual union all
select 456 col1, '李四' col2 from dual union all
select 789 col1, '王五' col2 from dual
)
select replace(WMSYS.WM_CONCAT(col2), ',', '-') from (
SELECT REGEXP_SUBSTR ('123-456-789', '[^-]+', 1,rownum) col3
FROM DUAL
CONNECT BY ROWNUM <=regexp_count(('123-456-789', '[^-]+')
) aa left join table1 bb on aa.col3=bb.col1
小灰狼W 2015-07-30
  • 打赏
  • 举报
回复
return早了。不管有多少行,都会在第一行以后跳出。另外赋值上也不太对
CREATE OR REPLACE FUNCTION  fn_GetDead (v_deadId varchar2)
return varchar2
is
 
v_deadString varchar2(100);
v_deadString_all VARCHAR2(4000);
cursor c_deadIdSpilt  --设置一个分割字符串游标--
 is
select *  from table(splitstr(''||v_deadId||'','-'));
c_row c_deadIdSpilt%rowtype;
 
begin  
   
 if  instr(v_deadId,'-') > 0 then  ---判读变量中是否含有"-"字符,如果有,则循环遍历这个字符,取出亡人姓名
  open c_deadIdSpilt;              --打开游标--
  loop
    fetch c_deadIdSpilt into c_row;
    EXIT WHEN c_deadIdSpilt%NOTFOUND;
      SELECT wrxm into v_deadString FROM wrxxb WHERE id=C_ROW.COLUMN_VALUE;
       
       v_deadString_all:=v_deadString_all||'-'||v_deadString;       
      
  end loop;
 
 close c_deadIdSpilt;

  return ltrim(v_deadString_all,'-');
 else
    
  SELECT wrxm INTO v_deadString FROM wrxxb WHERE id=''||v_deadId||'';
 
  return v_deadString;
 end if;
 
--异常处理--
exception
 
  when others then dbms_output.put_line('error');
  return -1;
end fn_GetDead;
/
CalvinR 2015-07-29
  • 打赏
  • 举报
回复
引用 2 楼 zbdzjx 的回复:
换个写法:
with table1 as
(
select 123 col1, '张三' col2 from dual union all
select 456 col1, '李四' col2 from dual union all
select 789 col1, '王五' col2 from dual
)
select replace(WMSYS.WM_CONCAT(col2), ',', '-') from (
SELECT REGEXP_SUBSTR ('123-456', '[^-]+', 1,rownum) col3
FROM DUAL
CONNECT BY ROWNUM <=
LENGTH ('123-456') - LENGTH (REPLACE ('123-456', '-', ''))+1
) aa left join table1 bb on aa.col3=bb.col1
我要的是一个函数 返回一个名字的拼接字符串
CalvinR 2015-07-29
  • 打赏
  • 举报
回复
引用 3 楼 maco_wang 的回复:
如果你的参数只有一个“-”,就不需要写这么复杂,也可以不用游标。 例如把-左边的对应的数据和-右边的对应的数据,分别查找到结果,然后拼接在一起即可。
不止一个“-” 可能有好多个
CalvinR 2015-07-29
  • 打赏
  • 举报
回复
引用 1 楼 maco_wang 的回复:
16022 对应的数据存在吗?
有数据的
叶子 2015-07-29
  • 打赏
  • 举报
回复
如果你的参数只有一个“-”,就不需要写这么复杂,也可以不用游标。 例如把-左边的对应的数据和-右边的对应的数据,分别查找到结果,然后拼接在一起即可。
zbdzjx 2015-07-29
  • 打赏
  • 举报
回复
换个写法:
with table1 as
(
select 123 col1, '张三' col2 from dual union all
select 456 col1, '李四' col2 from dual union all
select 789 col1, '王五' col2 from dual
)
select replace(WMSYS.WM_CONCAT(col2), ',', '-') from (
SELECT REGEXP_SUBSTR ('123-456', '[^-]+', 1,rownum) col3
FROM DUAL
CONNECT BY ROWNUM <=
LENGTH ('123-456') - LENGTH (REPLACE ('123-456', '-', ''))+1
) aa left join table1 bb on aa.col3=bb.col1
叶子 2015-07-29
  • 打赏
  • 举报
回复
16022 对应的数据存在吗?
卖水果的net 2015-07-29
  • 打赏
  • 举报
回复
2# 的写法非常好,建议你按他这个改进一下。
卖水果的net 2015-07-29
  • 打赏
  • 举报
回复
LZ 你自己写的那个函数,你要在后面加一个减号 即
v_deadId  := v_deadId  || '-'; 
-- 16021-16022-
zbdzjx 2015-07-29
  • 打赏
  • 举报
回复
引用 6 楼 TERMINATOR_LZQ 的回复:
[quote=引用 2 楼 zbdzjx 的回复:] 换个写法:
with table1 as
(
select 123 col1, '张三' col2 from dual union all
select 456 col1, '李四' col2 from dual union all
select 789 col1, '王五' col2 from dual
)
select replace(WMSYS.WM_CONCAT(col2), ',', '-') from (
SELECT REGEXP_SUBSTR ('123-456', '[^-]+', 1,rownum) col3
FROM DUAL
CONNECT BY ROWNUM <=
LENGTH ('123-456') - LENGTH (REPLACE ('123-456', '-', ''))+1
) aa left join table1 bb on aa.col3=bb.col1
我要的是一个函数 返回一个名字的拼接字符串[/quote] 建一个函数,'123-456'是传递进来的参数,table1对应你的wrxxb表,将我这个select出来的结果直接返回就可以了。 看了一下你的语句,下面这段语句: SELECT wrxm into v_deadString FROM wrxxb WHERE id=C_ROW.COLUMN_VALUE; v_deadString:=v_deadString||'-'; return v_deadString; 读出第一行后,就直接return跳出函数了。 这个return要放在else前面吧,这样才能出正确结果。

17,140

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧