ORA-22905:无法从非嵌套项访问行 之解决

今天笔者在帮同事写一个格式化日期函数的过程中,在调用管道(pipeline) 实现的函数时,遇到了一个ORACLE异常: ORA-22905:无法从非嵌套项访问行.

注:(有关嵌套表参见:http://blog.csdn.net/simonezhlx/archive/2008/10/28/3167343.aspx)

具体情况:为了实现日期字符串的格式化,需要对传入的字符串进行分拆.然后视情况补0后再连接成一个字符串.

为了实现该应用,创建了一个类型,两个函数.如下:

--创建类型

create or replace type type_split as table of varchar2(50);
--创建通用Split函数
create or replace function CommonSplit(sourceStr in varchar2,sepmark in varchar2)
return TYPE_SPLIT pipelined is
   l_idx  integer;
   v_list  varchar2(500) := sourceStr;
begin
  loop
      l_idx := instr(v_list,sepmark);
      if l_idx > 0 then
          pipe row(substr(v_list,1,l_idx-1));
          v_list := substr(v_list,l_idx+length(sepmark));
      else
          pipe row(v_list);
          exit;
      end if;
   end loop;
   return;
end CommonSplit;
--创建日期格式化函数
create or replace function FormatDateStr(SourceDate in varchar2)
 return varchar2 is
  sReturnValue varchar2(8);
  SepMark varchar2(1):='-';
  sTemp varchar2(20);
 cursor cu1(p1 varchar2,p2 varchar2) 
is select * from table(COMMONSPLIT(p1,p2)) ;
 
begin
  if LENGTH(SourceDate) <= 8 then
  --八位或不满足条件的输入日期
     sReturnValue := SourceDate;
  else
     if instr( SourceDate,SepMark ) > 0 then
      open cu1(SourceDate,SepMark);    

         loop
           fetch cu1 into sTemp;
           exit when cu1%notfound;
           if length(sTemp) = 1 then --补0
              sTemp:= '0' || sTemp;
           end if;
           sReturnValue:= sReturnValue || sTemp;
         end loop;
         close cu1;
     end if;
  end if;
  return(sReturnValue);
end FormatDateStr;

但编写完成在测试时发现在运行到红色字体也就是运行游标查询时会有异常出现(ORA-22905:无法从非嵌套项访问行).

尝试多次,均无果,最后只得变换方式,将游标改为无参,靠生成动态SQL来完成游标查询.结果问题解决.如下:

create or replace function FormatDateStr(SourceDate in varchar2)
 return varchar2 is
  sReturnValue varchar2(8);
  SepMark varchar2(1):='-';
  sTemp varchar2(20);
  V_SQL_SELECT VARCHAR2(400);
   TYPE V_CURSOR IS REF CURSOR;
   cu1 V_CURSOR;
--   cursor cu1(p1 varchar2,p2 varchar2)
 -- is select * from table(COMMONSPLIT(p1,p2)) ;
-- is select * from table(commonsplit('' || p1 || '','' || p2 || ''));
begin
  if LENGTH(SourceDate) <= 8 then
  --八位或不满足条件的输入日期
     sReturnValue := SourceDate;
  else
     if instr( SourceDate,SepMark ) > 0 then
         --open cu1(SourceDate,SepMark);   
         V_SQL_SELECT:='select * from table(COMMONSPLIT(''' || SourceDate
         || ''',''' || SepMark || '''))';    
         open cu1 for V_SQL_SELECT;
         loop
           fetch cu1 into sTemp;
           exit when cu1%notfound;
           if length(sTemp) = 1 then --补0
              sTemp:= '0' || sTemp;
           end if;
           sReturnValue:= sReturnValue || sTemp;
         end loop;
         close cu1;
     end if;
  end if;
  return(sReturnValue);
end FormatDateStr;

红色为修改后内容,但是始终不知道为什么使用参数方式会有问题.如有知者告之,笔者甚感之至.

你可能感兴趣的:(oracle,sql,list,function,table,Integer)