从存储过程或函数

时间:2015-10-12 17:47:40

标签: sql oracle

我无法执行存储过程以获取结果。目前,我想在toadeclipse或我正在使用的其他任何内容的输出窗口中显示结果。稍后,我想从程序中访问它们。暂时忽略程序部分,除非它是必不可少的。

我有这个存储过程代码:

create or replace procedure pottyuserange (p_date_format in varchar2,
                                       p_start_date in varchar2,
                                       p_end_date in varchar2,
                                       p_ref_cursor out sys_refcursor)
as
begin
  open p_ref_cursor for 
    select   to_char(time_range, p_date_format) as current_date,
         lm_search,
         ao_search,
         ro_search,
         fl_search,
         total
from     (select   trunc(time_range) time_range,
                   sum(case when porta_potty = 'LM' then 1 else 0 end) as lm_search,
                   sum(case when porta_potty = 'AO' then 1 else 0 end) as ao_search,
                   sum(case when porta_potty = 'RO' then 1 else 0 end) as ro_search,
                   sum(case when porta_potty = 'FL' then 1 else 0 end) as fl_search,
                   sum(case when porta_potty in ('LM', 'AO', 'RO', 'FL') then 1 else 0 end) as total           
          from     core.date_test
          where    trunc(time_range) >= to_date(p_start_date, p_date_format)
          and      trunc(time_range) <= to_date(p_end_date, p_date_format)
          group by trunc(time_range))
    order by time_range asc;
  end pottyuserange;
/

我正试图得到这样的结果:

variable rc refcursor;

BEGIN
    pottyuserange('YYYY-MM-DD', '2008-10-1', '2010-10-12', :rc);
END;

print rc;

这就是我得到的错误:

ORA-01722: invalid number
ORA-06512: at "core.pottyuserange", line 4
ORA-06512: at line 1

如何正确访问此数据,或将其转换为User-Defined Function? \

这是我尝试将其变成一个函数:

create or replace function pottyuserange (p_date_format in varchar2,
                                       p_start_date in varchar2,
                                       p_end_date in varchar2)
return result_set as rc sys_refcursor;

BEGIN

OPEN result_set FOR
    select   to_char(time_range, p_date_format) as current_date,
         lm_search,
         ao_search,
         ro_search,
         fl_search,
         total
from     (select   trunc(time_range) time_range,
                   sum(case when porta_potty = 'LM' then 1 else 0 end) as lm_search,
                   sum(case when porta_potty = 'AO' then 1 else 0 end) as ao_search,
                   sum(case when porta_potty = 'RO' then 1 else 0 end) as ro_search,
                   sum(case when porta_potty = 'FL' then 1 else 0 end) as fl_search,
                   sum(case when porta_potty in ('LM', 'AO', 'RO', 'FL') then 1 else 0 end) as total           
          from     core.date_test
          where    trunc(time_range) >= to_date(p_start_date, p_date_format)
          and      trunc(time_range) <= to_date(p_end_date, p_date_format)
          group by trunc(time_range))
    order by time_range asc;
    return result_set;
  end pottyuserange;
/

我上面提到的错误是:PLS-00201: identifier 'RESULT_SET' must be declared

编辑TIME_RANGEDATEPORTA_POTTY是varchar2。

1 个答案:

答案 0 :(得分:1)

(方法1)创建自己的集合类型并更改函数以返回此类型的对象:

 create or replace type tp_potty as object (
  current_date varchar2(20), lm_search number(6), ao_search number(6), 
  ro_search number(6), fl_search number(6), total number(6));

create or replace type tp_potty_tbl as table of tp_potty;

create or replace function pottyuserange (p_date_format in varchar2,
                                          p_start_date in varchar2, 
                                          p_end_date in varchar2)
                                   return tp_potty_tbl is
  potty_tbl tp_potty_tbl;
begin
  select cast(multiset(
      select to_char(time_range, p_date_format) as current_date,
             lm_search, ao_search, ro_search, fl_search, total
      from  (select    trunc(time_range) time_range,
                       sum(case when porta_potty = 'LM' then 1 else 0 end) lm_search,
                       sum(case when porta_potty = 'AO' then 1 else 0 end) ao_search,
                       sum(case when porta_potty = 'RO' then 1 else 0 end) ro_search,
                       sum(case when porta_potty = 'FL' then 1 else 0 end) fl_search,
                       sum(case when porta_potty in ('LM', 'AO', 'RO', 'FL') 
                                then 1 else 0 end) total
              from     date_test
              where    trunc(time_range) >= to_date(p_start_date, p_date_format)
              and      trunc(time_range) <= to_date(p_end_date, p_date_format)
              group by trunc(time_range))
        order by time_range asc) as tp_potty_tbl) into potty_tbl from dual;
    return potty_tbl;
end pottyuserange;

现在运行:

select * from table(pottyuserange('yyyy-mm-dd', '2015-10-10', '2015-10-15'))

CURRENT_DATE         LM_SEARCH AO_SEARCH RO_SEARCH FL_SEARCH   TOTAL
-------------------- --------- --------- --------- --------- -------
2015-10-12                   1         0         0         0       1
2015-10-13                   1         0         0         0       1
2015-10-14                   0         0         0         0       0

(方法2)从PL / SQL块中的函数返回的游标的列表输出如下:

create or replace function potty2 (p_date_format in varchar2,
  p_start_date in varchar2,p_end_date in varchar2) return sys_refcursor is

  result_set sys_refcursor;

BEGIN

OPEN result_set FOR
    select   to_char(time_range, p_date_format) as current_date,
         lm_search, ao_search, ro_search, fl_search, total
from     (select   trunc(time_range) time_range,
                   sum(case when porta_potty = 'LM' then 1 else 0 end) as lm_search,
                   sum(case when porta_potty = 'AO' then 1 else 0 end) as ao_search,
                   sum(case when porta_potty = 'RO' then 1 else 0 end) as ro_search,
                   sum(case when porta_potty = 'FL' then 1 else 0 end) as fl_search,
                   sum(case when porta_potty in ('LM', 'AO', 'RO', 'FL') 
                            then 1 else 0 end) as total           
          from     date_test
          where    trunc(time_range) >= to_date(p_start_date, p_date_format)
          and      trunc(time_range) <= to_date(p_end_date, p_date_format)
          group by trunc(time_range))
    order by time_range asc;
    return result_set;
end potty2;

PL / SQL块:

declare 
  cur sys_refcursor;
  v1 varchar2(20); v2 number(6); v3 number(6); v4 number(6); v5 number(6); v6 number(6);
begin
  cur := potty2('yyyy-mm-dd', '2015-10-10', '2015-10-15');
  loop
    fetch cur into v1, v2, v3, v4, v5, v6;
    exit when cur%notfound;
    dbms_output.put_line(v1||' '||v2||' '||v3||' '||v4||' '||v5||' '||v6);
  end loop;
  close cur; 
end;

我的回答基于这篇文章:PL/SQL 101 : Understanding Ref Cursors