如何让存储过程在一个存储过程中完成所有操作,而不是两个单独的存储过程

时间:2018-04-23 15:18:51

标签: oracle plsql

所以我试图按小时将聚合(求和)值插入值表中。按小时插入值后,我想在同一过程中按天插入综合总和。有没有办法我可以让存储过程按小时完成插入,然后让它通过对在“小时”期间插入的数据进行求和来绘制光标。处理?我是否需要提交第一个事务,然后在不久之后创建另一个游标?

以下是一些示例数据:

已按小时汇总/汇总的查询结果:

SUM (VALUE_TX)   UTC_OFFSET   DATA_DATE    HR
   5              8           902018      1
  10              8           902018      2
   4              8           902018      3

在将上面的第一个结果集插入表格后,我想要插入的内容。我将从我将要插入的同一个表中绘制这些值。

SUM (VALUE_TX)   UTC_OFFSET   DATA_DATE    HR
   19                8           902018    null

我正在考虑做以下事情,但我不确定这是否是最好的方法。我将按data_Date分组以形成第二个游标。

Create or replace procedure AGG_HOURLY_DAILY IS
CURSOR c1 is
Select sum(value_Tx) as sum_of_values
     , utc_offset
     , data_date
     , hr
  from value
 group by data_date, utc_offset, hr
where HR is not null;
l_var c1%ROWTYPE;
CURSOR c2 is
Select sum(value_tx)
     , utc_offset
     , data_date
     , hr
 group by data_date, utc_offset, hr
Where HR is null;
k_var c2%rowtype;
BEGIN
Open C1;
LOOP;
  FETCH c1 into l_var;
 EXIT WHEN c1%NOTFOUND;
  Insert into value(value_id, value_tx, utc_offset, data_date, hr)
             values(null, l_var.sum_of_values, l_var.utc_offset, l_var.data_date, l_var.hr);
END LOOP;
CLOSE C1;
OPEN C2;
LOOP;
  FETCH c2 into k_var;
 EXIT WHEN c2%NOTFOUND;
  Insert into value(value_id, value_tx, utc_offset, data_date, hr)
             values(null, l_var.sum_of_values, l_var.utc_offset, l_var.data_date, l_var.hr);
END LOOP;
Close c1;
Close c2;
END AGG_HOURLY_DAILY;

注意:Value_ID由我创建的序列/触发器自动生成

2 个答案:

答案 0 :(得分:2)

也许你想要这样的东西:

with demo (value_tx, utc_offset, data_date, hr)
as   ( select 1, 8, '902018', 1 from dual union all
       select 2, 8, '902018', 1 from dual union all
       select 2, 8, '902018', 1 from dual union all
       select 4, 8, '902018', 2 from dual union all
       select 6, 8, '902018', 2 from dual union all
       select 1, 8, '902018', 3 from dual union all
       select 2, 8, '902018', 3 from dual union all
       select 1, 8, '902018', 3 from dual )
select sum(value_tx), utc_offset, data_date, hr
from   demo
group by grouping sets ((utc_offset, data_date, hr), (utc_offset, data_date))
order by hr nulls last;

SUM(VALUE_TX) UTC_OFFSET DATA_DATE         HR
------------- ---------- --------- ----------
            5          8 902018             1
           10          8 902018             2
            4          8 902018             3
           19          8 902018    

GROUPING SETS子句实际上是说您需要两个GROUP BY操作:一个在(utc_offset, data_date, hr)上,另一个在(utc_offset, data_date)上。

Read more in the documentation

答案 1 :(得分:1)

在第一步中,用简单的INSERT ... SELECT语句替换游标:

  Insert into value( value_tx, utc_offset, data_date, hr)
  SELECT sum(value_Tx) as sum_of_values
     , utc_offset
     , data_date
     , hr
  from value
 group by data_date, utc_offset, hr
where HR is not null;

Insert into value( value_tx, utc_offset, data_date, hr)
Select sum(value_tx)
     , utc_offset
     , data_date
     , hr
 group by data_date, utc_offset, hr
Where HR is null;

由于这种简化,很容易看出两个查询只有一个元素不同:HR is NULLHR is NOT NULL。 因此,上面插入两行的两个查询可以简化为插入相同两行的一个:

Insert into value( value_tx, utc_offset, data_date, hr)
SELECT sum_tx, utc_offset, data_date, hr
FROM (
   Select CASE WHEN hr IS NULL THEN 1 ELSE 2 END as xxx
            , sum(value_tx) as sum_tx
            , utc_offset
            , data_date
            , hr
   group by CASE WHEN hr IS NULL THEN 1 ELSE 2 END,
         data_date, utc_offset, hr
)
;
  

所以我不需要PL / SQL吗?有没有办法可以做到这一点   使用PL / SQL?

您可以在程序中执行此操作,无需程序即可 如果你想要一个程序,只需:

Create or replace procedure AGG_HOURLY_DAILY IS
BEGIN
  Insert into value( value_tx, utc_offset, data_date, hr)
  SELECT sum_tx, utc_offset, data_date, hr
    FROM (
       Select CASE WHEN hr IS NULL THEN 1 ELSE 2 END as xxx
                , sum(value_tx) as sum_tx
                , utc_offset
                , data_date
                , hr
       group by CASE WHEN hr IS NULL THEN 1 ELSE 2 END,
             data_date, utc_offset, hr
    )
    ;
END;
/