Oracle Cursor将逐步完成记录

时间:2012-12-07 13:18:11

标签: oracle cursor

有人可以帮助我以下。编写光标很容易,但我不知道如何在REFVAL更改时进行测试。到目前为止,我的光标位于下方。

无法将光标分组到REFVAL。可以认为它是基于一系列发票行,需要为该发票上的总箱子加起来。

类似的东西:

REFVAL           PAYAMNT       INVOICE_DETAIL

12/00001/DA      £420          Recurring fee
12/00001/DA      £300          CRB check
12/00001/DA      £170          Plate fee
12/00002/JV      £70           SQL assistance
12/00002/JV      £30           Loader assistance

因此,当单步执行游标时,我可以将详细信息从12/00001/DA写入三行,然后写出12/00001/DA (£890)的总数,然后写出12/00002/JV中的详细信息,然后是摘要行那个。

因此,脚本需要知道REFVAL更改的时间

到目前为止我所拥有的是:

DECLARE
  CURSOR c1 IS 
     SELECT refval,amt from johan;

  Grandtotal INTEGER := 0;
  REF_total  Integer := 0;
  REFVAL     varchar(20);
BEGIN
  OPEN c1;
  LOOP
    FETCH c1 INTO refval,ref_total;
    IF c1%notfound THEN
      EXIT;
    END IF;

     dbms_output.put_line('TOtal for '|| refval || ': ' || ref_total);
     Grandtotal := Grandtotal + ref_total;
   END LOOP;

   IF c1%ISOPEN THEN  -- cursor is open
     CLOSE c1;
   END IF;

   dbms_output.put_line('Grandtotal: '||Grandtotal);
 END;
 /

2 个答案:

答案 0 :(得分:3)

如果我正确理解了您的要求,那么就不需要对数据进行过程处理,可以使用rollup子句的group by扩展在SQL中完成,以计算总数和总计。这是一个例子:

SQL> with t1 as(
  2    select '12/00001/DA' as REFVAL,  420 as PAYAMNT, 'Recurring fee' as INVOICE_DETAIL from dual union all
  3    select '12/00001/DA',  300,   'CRB check' from dual union all
  4    select '12/00001/DA',  170,   'Plate fee' from dual union all
  5    select '12/00002/JV',  70 ,   'SQL assistance' from dual union all
  6    select '12/00002/JV',  30 ,   'Loader assistance' from dual
  7  )
  8  select nvl(REFVAL, 'GRAND TOTAL:') as REFVAL
  9       , case
 10             when (INVOICE_DETAIL is null) and (REFVAL is not null)
 11             then 'SUB-TOTAL:'
 12             else INVOICE_DETAIL
 13         end  as INVOICE_DETAIL
 14       , sum(PAYAMNT)
 15        
 16     from t1
 17    group by rollup(REFVAL, INVOICE_DETAIL)
 18  ;

REFVAL       INVOICE_DETAIL           END
------------ ----------------- ----------
12/00001/DA  CRB check                300
12/00001/DA  Plate fee                170
12/00001/DA  Recurring fee            420
12/00001/DA  SUB-TOTAL:               890

12/00002/JV  SQL assistance            70
12/00002/JV  Loader assistance         30
12/00002/JV  SUB-TOTAL:               100

GRAND TOTAL:                          990

8 rows selected 

答案 1 :(得分:1)

DECLARE
   CURSOR c1
   IS
      SELECT   refval,
               amt,
               DENSE_RANK () OVER (PARTITION BY REFVAL ORDER BY rowid) rnk   
        FROM   johan;

   Grandtotal   INTEGER := 0;
   REF_total    INTEGER := 0;
   REFVAL       VARCHAR (20);
   v_new_rank   PLS_INTEGER;  
   v_old_rank   PLS_INTEGER;
   v_start      PLS_INTEGER := 1;    --just to intialize v_old_rank
BEGIN
   OPEN c1;

   LOOP
      FETCH c1 INTO   refval, ref_total, v_new_rank;

      EXIT WHEN c1%NOTFOUND;

      IF v_start = 1
      THEN
         v_old_rank := v_new_rank;
         v_start := v_start + 1;
      END IF;

      DBMS_OUTPUT.put_line ('TOtal for ' || refval || ': ' || ref_total);
      Grandtotal := Grandtotal + ref_total;

      IF v_old_rank <> v_new_rank
      THEN
         v_old_ref_val := v_new_rank;

   --you can print the total per refval group
    DBMS_OUTPUT.PUT_LINE ('do something');
      END IF;
   END LOOP;

   IF c1%ISOPEN
   THEN
      -- cursor is open
      CLOSE c1;
   END IF;

   DBMS_OUTPUT.put_line ('Grandtotal: ' || Grandtotal);
END;
/

当你从光标c1中选择时,它看起来如下所示

REFVAL           PAYAMNT              rnk

12/00001/DA      £420                 1
12/00001/DA      £300                 1
12/00001/DA      £170                 1
12/00002/JV      £70                  2
12/00002/JV      £30                  2