2013-11-27 27 views
0

我有一個觸發自動,但只能在同一個會話中執行一次執行一次,然後什麼也不做我有一個觸發自動,但只是在同一會話

CREATE OR REPLACE TRIGGER tdw_insert_unsus 
BEFORE INSERT ON unsuscription_fact FOR EACH ROW 
DECLARE 
PRAGMA AUTONOMOUS_TRANSACTION; 
v_id_suscription    SUSCRIPTION_FACT.ID_SUSCRIPTION%TYPE; 
v_id_date_suscription   SUSCRIPTION_FACT.ID_DATE_SUSCRIPTION%TYPE; 
v_id_date_unsuscription  SUSCRIPTION_FACT.ID_DATE_UNSUSCRIPTION%TYPE; 
v_suscription     DATE; 
v_unsuscription    DATE; 
v_live_time     SUSCRIPTION_FACT.LIVE_TIME%TYPE; 
BEGIN 
    SELECT id_suscription, id_date_suscription 
    INTO v_id_suscription, v_id_date_suscription 
    FROM(
     SELECT id_suscription, id_date_suscription 
     FROM suscription_fact 
     WHERE id_mno = :NEW.ID_MNO 
     AND id_provider = :NEW.ID_PROVIDER 
     AND ftp_service_id = :NEW.FTP_SERVICE_ID 
     AND msisdn = :NEW.MSISDN 
     AND id_date_unsuscription IS NULL 
     ORDER BY id_date_suscription DESC 
    ) 
    WHERE ROWNUM = 1; 

    -- calculate time 
    v_unsuscription := to_date(:NEW.id_date_unsuscription,'yyyymmdd'); 
    v_suscription := to_date(v_id_date_suscription,'yyyymmdd'); 
    v_live_time := (v_unsuscription - v_suscription); 

    UPDATE suscription_fact SET id_date_unsuscription = :NEW.id_date_unsuscription, 
    id_time_unsuscription = :NEW.id_time_unsuscription, live_time = v_live_time 
    WHERE id_suscription = v_id_suscription; 

    COMMIT; 

    EXCEPTION 
     WHEN NO_DATA_FOUND THEN 
     ROLLBACK; 
END; 
/

如果我插入值,效果很好第一Ø第二次,但之後沒有工作,但如果我退出了會議,並登錄適用於第一或第二插入 是什麼問題?我用的Oracle 10g

+0

也許你正在碰到no_data_found異常?取出異常處理程序,看看是否會拋出錯誤。 – OldProgrammer

+0

它幾乎總是一個錯誤(至少不好的代碼味道)使用自動觸發器除了日誌以外的任何事情 –

回答

4

您使用的自治事務來解決的事實觸發器無法查詢其表本身。你遇到了臭名昭着的變異表錯誤,你發現將觸發器聲明爲自治事務會導致錯誤消失。

沒有運氣,你雖然,這根本不會解決問題:

  • 首先,任何事務邏輯都將丟失。您無法回滾suscription_fact表中的更改,它們是承諾,而您的主要事務不是並且可能會回滾。所以你也失去了數據的完整性。
  • 觸發器無法看到新行,因爲新行尚未提交!由於觸發器在獨立事務中運行,因此它看不到主事務發生的未提交更改:您將遇到完全錯誤的結果。

這就是爲什麼你不應該在自治事務中做任何業務邏輯。 (有合法的應用程序,但幾乎完全限於日誌記錄/調試)。

在你的情況,你應該:

  1. 更新你的邏輯,這樣它並不需要查詢您的表(更新suscription_fact僅如果新行比存儲在id_date_unsuscription舊值更近)。
  2. 忘掉在觸發器中使用業務邏輯,並使用正確更新所有表或使用視圖的過程,因爲在這裏我們有明確的冗餘數據情況。
  3. 使用workaround that actually works (by Tom Kyte)

我強烈建議在這裏使用(2)。不要使用觸發器來編寫業務邏輯。他們很難寫出沒有錯誤,更難以維持。使用程序保證所有相關的代碼被分組在一個地方(一個程序包或一個程序),易於閱讀和遵循,並且沒有無法預料的後果。