溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

APP_CALCULATE.RUNNING_TOTAL用法

發(fā)布時間:2020-08-10 17:59:07 來源:ITPUB博客 閱讀:188 作者:kawontony 欄目:關(guān)系型數(shù)據(jù)庫

有時候需要顯示某個欄位的匯總數(shù)量,且在例如新增、刪除、修改記錄的時候,匯總項的值要相應(yīng)地改變,如果直接使用Form中的SUM屬性功能,對于清除等操作要進(jìn)行復(fù)雜處理。Oracle提供了APP_CALCULATE.RUNNING_TOTAL來實現(xiàn)這種需求,封裝在APPCORE.PLL中。

For Example: 
要匯總的ITEM為:LINES.QUANTITY,要顯示匯總結(jié)果的BLOCK為HEADERS 
1.HEADERS里建立要顯示的匯總結(jié)果ITEM,如QTY_SUM 
2.HEADERS里建立兩個非數(shù)據(jù)庫項,分別命名為QTY_SUM_RTOT_OLD和QTY_SUM_RTOT_DB(Number型) 
3.LINES里建立兩個非數(shù)據(jù)庫項,分別命名為QUANTITY_RTOT_OLD和QUANTITY_RTOT_DB(Number型) 
4.建立存儲過程來包裝APP_CALCULATE.RUNNING_TOTAL 
例: 
PROCEDURE RUNNING_TOTAL_QUANTITY(EVENT VARCHAR2) IS 
BEGIN 
  APP_CALCULATE.RUNNING_TOTAL(EVENT, 'LINES.QUANTITY', 'HEADERS.QTY_SUM'); 
END; 
--在TRIGGER中調(diào)用RUNNING_TOTAL_QUANTITY來進(jìn)行計算處理 
5.:LINES.QUANTITY的WHEN-VALIDATE-ITEM Trigger中寫RUNNING_TOTAL_QUANTITY('WHEN-VALIDATE-ITEM');

    如果要匯總的欄位來自多個欄位的運算,需要在每個欄位的WHEN-VALIDATE-ITEM時寫運算重新計算值賦給要匯總的欄位。

6.:HEADERS的POST-QUERY Trigger中從數(shù)據(jù)庫中抓取初始的匯總值,例:

Declare 
  V_SUM NUMBER; 
BEGIN 
  SELECT NVL(SUM(QUANTITY), 0) 
       INTO V_SUM 
     FROM LINES 
   WHERE HEADER_ID = :HEADERS.HEADER_ID; 
  :HEADERS.QTY_SUM                   := V_SUM; 
    :HEADERS.QTY_SUM_RTOT_DB := V_SUM;----------------------注① 
END;

7.:LINES的如下TRIGGER中寫相應(yīng)代碼: 
--KEY-DELREC 
RUNNING_TOTAL_QUANTITY('KEY-DELREC'); 
DELETE_RECORD;

RUNNING_TOTAL_QUANTITY('UNDELETE');----------------------注③

--KEY-DUPREC 
RUNNING_TOTAL_QUANTITY('KEY-DUPREC'); 
DUPLICATE_RECORD;

--KEY-CLRREC 
RUNNING_TOTAL_QUANTITY('KEY-CLRREC'); 
CLEAR_RECORD;--(網(wǎng)上例子為:APP_FOLDER.EVENT('KEY-CLRREC');)

--POST-QUERY 
RUNNING_TOTAL_QUANTITY( 'POST-QUERY' );

--WHEN-CLEAR-BLOCK 
RUNNING_TOTAL_QUANTITY( 'WHEN-CLEAR-BLOCK' );----------------------注②

注:網(wǎng)上例子中還有post_insert,post_update,pre_record中寫,我目前沒寫,測試OK,不知道會有什么漏洞,暫時沒測出來。

另外上面的鏈接中,作者的例子會有問題,像鏈接文章評論所說,作者需增加  注①  的代碼  ,即  WHEN-CLEAR-BLOCK的代碼需和注①同時存在(查詢發(fā)現(xiàn)EBS中PO的畫面也是這么做的)。

最初我沒有寫  注②  和  注①  的代碼  ,后經(jīng)測試,  缺少這兩部分會出現(xiàn)問題  ,還是舉個例子說吧:

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※

例:  Line項只有一條記錄,值為100,

1)正常查詢出來記錄后,匯總欄顯示100;

2)修改記錄值為99,匯總欄變?yōu)?9;

3)按F11,會提示“是否保存記錄”,選擇“否”;

      --此時匯總欄值為99(正常情況下此時匯總欄顯示100)。

4)執(zhí)行Ctrl+F11;

      --此時匯總欄值依然為99(正常情況下此時匯總欄顯示100,(且很大問題是此時Line值為100,匯總為99))。

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※

所以:注②  注①一定要寫。

注③:  Block的Delete Allowed設(shè)置為No,由于種種原因,Delete按鈕是亮的。這種情況下,點擊  Delete按鈕  的時候會提示

            FRM-41049:You cannot delete this record.但是匯總量會被減掉,一直點下去,會一直減掉..直至負(fù)NNNN... APP_CALCULATE.RUNNING_TOTAL用法

            所以加上  注③,以避免這種情況時匯總量的錯誤。

至于其它在  APP_CALCULATE.RUNNING_TOTAL  中涉及到的 Trigger中是否要寫以及如何寫,還未測試,目前為止,應(yīng)用正常。

(有一點問題,即"新增一條記錄,保存,然后點擊clear-record按鈕",數(shù)量會減掉,還未解決,其余Trigger應(yīng)該也需要加上,但是有幾個Trigger好像在Block下面沒有,但又有其它Trigger調(diào)用在它們中產(chǎn)生的全局變量,暫時未過多測試。。Busy。。)


另外,如果匯總結(jié)果要拿來與其它值作比較,比如超過了某個值則raise error,則要注意running_total和比較大小兩者的先后順序。

如在when-validate-item時比較,則在此trigger中先running_total,后比較,否則...

--------------------------------------------------------------------------------------------------------------------------------------------------

附APP_CALCULATE.RUNNING_TOTAL原代碼:

PACKAGE BODY app_calculate IS

  PROCEDURE running_total(event        VARCHAR2, 
                          source_field VARCHAR2, 
                          total_field  VARCHAR2) IS 
    Last_Val_Field  VARCHAR2(61) := Source_Field || '_RTOT_OLD'; 
    DB_Source_Field VARCHAR2(61) := Source_Field || '_RTOT_DB'; 
    DB_Total_Field  VARCHAR2(61) := Total_Field || '_RTOT_DB'; 
    Last_Value      NUMBER; 
    Source_Value    NUMBER; 
    DB_Source_Value NUMBER; 
    Total_Value     NUMBER := NVL(name_in(Total_Field), 0); 
    DB_Total_Value  NUMBER := NVL(name_in(DB_Total_Field), 0); 
    New_Total       NUMBER; 
    Form_Id         FORMMODULE; 
  BEGIN 
    COPY('Entering app_calculate.running_total.  Event is ' || event || '.', 
         'global.frd_debug'); 
    IF (event <> 'WHEN-CLEAR-BLOCK') THEN 
      Last_Value      := NVL(name_in(Last_Val_Field), 0); 
      Source_Value    := NVL(name_in(Source_Field), 0); 
      DB_Source_Value := NVL(name_in(DB_Source_Field), 0); 
    END IF; 
   
    IF (event = 'POST-QUERY') THEN 
      copy(to_char(Source_Value), DB_Source_Field); 
      copy(to_char(Source_Value), Last_Val_Field); 
     
    ELSIF (event = 'WHEN-CLEAR-BLOCK') THEN 
      IF (Total_Value <> DB_Total_Value) THEN 
        copy(to_char(DB_Total_Value), Total_Field); 
      END IF; 
     
    ELSIF (event = 'WHEN-VALIDATE-ITEM') THEN 
      IF (Source_Value <> Last_Value) THEN 
        New_Total := Total_Value - Last_Value + Source_Value; 
        copy(to_char(New_Total), Total_Field); 
        copy(to_char(Source_Value), Last_Val_Field); 
      END IF; 
     
    ELSIF (event = 'KEY-DELREC') THEN 
      IF (Last_Value <> 0) THEN 
        New_Total := Total_Value - Last_Value; 
        copy(to_char(New_Total), Total_Field); 
      END IF; 
      copy(to_char(Source_Value), Last_Val_Field); 
     
    ELSIF (event IN ('POST-INSERT', 'POST-UPDATE')) THEN 
      IF (Source_Value <> DB_Source_Value) THEN 
        copy(to_char(DB_Source_Value), Last_Val_Field); 
        copy(to_char(Source_Value), DB_Source_Field); 
      END IF; 
     
    ELSIF (event = 'PRE-RECORD') THEN 
      IF (Source_Value <> Last_Value) THEN 
        Form_Id := Find_Form(Get_Application_Property(Current_Form_Name)); 
        IF (Name_In('GLOBAL.RTOT_' || 
                    substr(source_field, 
                           1, 
                           least(instr(source_field, '.') - 1, 15)) || 
                    to_char(Form_id.id)) = 'N') THEN 
          copy(to_char(Last_Value), DB_Source_Field); 
        END IF; 
        copy(to_char(Source_Value), Last_Val_Field); 
      END IF; 
     
    ELSIF (event = 'PRE-COMMIT') THEN 
      Form_Id := Find_Form(Get_Application_Property(Current_Form_Name)); 
      copy('N', 
           'GLOBAL.RTOT_' || 
           substr(source_field, 1, least(instr(source_field, '.') - 1, 15)) || 
           to_char(Form_id.id)); 
     
    ELSIF (event = 'POST-FORMS-COMMIT') THEN 
      Form_Id := Find_Form(Get_Application_Property(Current_Form_Name)); 
      copy('Y', 
           'GLOBAL.RTOT_' || 
           substr(source_field, 1, least(instr(source_field, '.') - 1, 15)) || 
           to_char(Form_id.id)); 
      IF (Total_Value <> DB_Total_Value) THEN 
        copy(to_char(Total_Value), DB_Total_Field); 
      END IF; 
     
    ELSIF (event = 'UNDELETE') THEN 
      New_Total := Total_Value + Source_Value; 
      copy(to_char(New_Total), Total_Field); 
      copy(to_char(Source_Value), Last_Val_Field); 
     
    ELSIF (event = 'KEY-DUPREC') THEN 
      New_Total := Total_Value + Source_Value; 
      copy(to_char(New_Total), Total_Field); 
      copy(to_char(Source_Value), Last_Val_Field); 
      copy(NULL, DB_Source_Field); 
     
    ELSIF (event = 'KEY-CLRREC') THEN 
      IF (Last_Value <> DB_Source_Value) THEN 
        New_Total := Total_Value - Last_Value + DB_Source_Value; 
        copy(to_char(New_Total), Total_Field); 
      END IF; 
    ELSE 
      message('Invalid event ' || event || 
              ' in app_calulate.running_total'); 
    END IF; 
    COPY('Completed app_calculate.running_total.  Event is ' || event || '.', 
         'global.frd_debug'); 
   
  END running_total;

END app_calculate;


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI