2014-10-11 37 views
-2

我想要做的是減少'Vehicle'表中每輛車的價值,以便當日期達到'LastUpdate'值後一個月'Value'列減少了2.5%。觸發器應該在數據庫登錄後運行。問題是,DBA可能不會每天都登錄到數據庫,因此如果自上次登錄六個月後,觸發器將循環,將值減少2.5%並執行ADD_MONTHS(LastUpdate,1)。每月減少車輛的價格

我對於將計算值的函數代碼:

REATE OR REPLACE FUNCTION fn_Vehicle_Value 
(VehicleNumber IN NUMBER, 
VehicleValue IN OUT NUMBER) 
RETURN NUMERIC 
IS 
BEGIN 
VehicleValue := VehicleValue - (VehicleValue * 0.025); 
RETURN VehicleValue; 
END; 
/

這是我在創建系統觸發嘗試:

CREATE OR REPLACE TRIGGER tg_VehicleDepreciate 
AFTER LOGON ON DATABASE 
IS 
CURSOR vehicle_cur IS SELECT "VALUE", LastUpdate FROM Vehicle; 
BEGIN 
FOR vehicle_rec IN vehicle_cur LOOP 

     WHILE LastUpdate < SYSDATE LOOP 
      LastUpdate."Value" := fn_Vehicle_Update("VALUE"); 

      UPDATE Vehicle 
      SET LastUpdate := ADD_MONTHS(LastUpdate, 1) 
       WHERE Vehicle# = vehicle_cur.Vehicle#; 

     END LOOP; 


EXIT WHEN vehicle_cur%NOTFOUND; 
END LOOP 
END; 
/

從我可以告訴,我的功能是正確的。但觸發不編譯,併產生下列錯誤報告:

錯誤報告 - ORA-04079:無效觸發規範 04079. 00000 - 「無效的觸發規範」 *原因:CREATE TRIGGER語句無效。 *操作:檢查語句的正確語法。

我猜這是一個語法錯誤,但也可能有一個邏輯錯誤,我不能解決。

+3

爲什麼不只是創建一個視圖來計算這個「即時」?我認爲沒有必要爲現有數據(可能需要「開始日期」或「交通工具」表中的「創建日期」)創建一個觸發器,它可以從現有數據中派生出來 – 2014-10-11 08:31:24

+0

它是一個單獨的任務,我必須按照我所說的去做。導師告訴我們我們需要使用功能和觸發器。 – Tom 2014-10-11 08:41:31

+1

聽起來有點愚蠢,通過'AFTER LOGON ON DATABASE'觸發器觸發你的更新。爲什麼不創建一個'SCHEDULER JOB'並且每半夜運行一次呢? – 2014-10-11 13:04:47

回答

0

SHOW ERRORS編譯你的觸發器後會顯示所有錯誤。

這裏有一些..
1)在更新,它只是SET somecolumn = Somevalue
2)甲骨文隱含打開遊標與FOR循環使用時關閉來。
3)使用FOR循環後,取出的結果應該像.. Forloopvariable.column-name
4)將Vehicle#添加到您的光標。
5)添加了V_date邏輯。

CREATE OR REPLACE TRIGGER tg_VehicleDepreciate 
AFTER LOGON ON DATABASE 
IS 
CURSOR vehicle_cur IS SELECT "VALUE", LastUpdate ,Vehicle# FROM Vehicle; 
V_date DATE; 
BEGIN 
FOR vehicle_rec IN vehicle_cur LOOP 

     V_date := vehicle_rec.LastUpdate; 

     WHILE V_date < SYSDATE LOOP 
      /* what are you trying here? */ 
      ---vehicle_rec."Value" := fn_Vehicle_Update("VALUE"); 

      UPDATE Vehicle 
      SET LastUpdate = ADD_MONTHS(LastUpdate, 1) 
       WHERE Vehicle# = vehicle_rec.Vehicle#; 

      V_date := ADD_MONTHS(V_date,1); 

     END LOOP; 

END LOOP 
END; 
/