2014-06-09 54 views
0

我想計算我的表的一列(PRA_COEFF)(RAPPORT_VISITE)中給定字段(PRA_NUM)的值的平均值,當我添加或更改它的一行時。然後我想在另一個表(PRACTITIONER)中將此值保存到上面給出的值PRA_NUM的PRA_NUM行。如何從Oracle 10g中獲取被稱爲觸發器的表字段?

CREATE TABLE "RAPPORT_VISITE" 
(
"RAP_NUM" NUMBER (10,0), 
"PRA_NUM" NUMBER (10,0), 
"PRA_COEFF" NUMBER (10,0), 
) 

CREATE TABLE "PRATICIEN" 
(
"PRA_NUM" NUMBER (10,0), 
"PRA_COEFCONF" NUMBER 
) 

觸發被稱爲添加或修改RAPPORT_VISITE表時。我試過這樣,但我無法檢索受觸發器影響的行,因此我需要讀取PRA_NUM。

create or replace TRIGGER UDPATE_PRAT_COEFCONF 
    AFTER INSERT or UPDATE ON RAPPORT_VISITE 

    DECLARE 
    somme NUMBER; 
    nb NUMBER; 
    moyenne NUMBER; 
    rapport NUMBER; 
    pra_id NUMBER; 

BEGIN 

    /*SELECT MAX(RAP_NUM) INTO rapport FROM RAPPORT_VISITE; // Not want I need in case where I modify a row... */ 
    SELECT PRA_NUM INTO pra_id FROM RAPPORT_VISITE WHERE RAP_NUM=rapport; 
    SELECT SUM(PRA_COEFF) INTO somme FROM RAPPORT_VISITE WHERE PRA_NUM=pra_id; 
    SELECT COUNT(*) INTO nb FROM RAPPORT_VISITE WHERE PRA_NUM=pra_id; 

    IF (nb != 0) THEN 
    moyenne := somme/nb; 
    moyenne := TRUNC (moyenne,1); 
    UPDATE PRATICIEN SET PRA_COEFCONF=moyenne WHERE PRA_NUM=pra_id; 
    END IF; 

END; 

回答

1

這裏有2個限觸發通常有:

  1. 調用時爲所有受影響的記錄,你不知道究竟發生了變化

  2. 時調用個人記錄(FOR EACH ROW),您被限制訪問修改表

爲了解決這一限制,從的Oracle 11g開始,我們可以使用compound trigger

CREATE OR REPLACE TRIGGER <trigger-name> 
FOR <trigger-action> ON <table-name> 
COMPOUND TRIGGER 

-- Global declaration. 
g_global_variable VARCHAR2(10); 
-- block 1 
BEFORE STATEMENT IS 
BEGIN 
NULL; -- Do something here. 
END BEFORE STATEMENT; 
-- block 2 
BEFORE EACH ROW IS 
BEGIN 
NULL; -- Do something here. 
END BEFORE EACH ROW; 
-- block 3 
AFTER EACH ROW IS 
BEGIN 
NULL; -- Do something here. 
END AFTER EACH ROW; 
-- block 4 
AFTER STATEMENT IS 
BEGIN 
NULL; -- Do something here. 
END AFTER STATEMENT; 

END <trigger-name>; 

而且看起來這是你所需要的。在塊1中,初始化您的變量,在塊2或3中收集各行的更改,然後在塊4中使用該信息創建業務邏輯的其餘部分。


如果我們受限於10g,那麼我們可以使用包變量來模擬複合觸發器。 該解決方案是有限的,因爲會話的包變量是全局的。如果進行一次會話,你有兩個類似的操作,他們的結果將被合併。

下面是解

  1. 你將有3個獨立的觸發器,這將表示塊1,(2或3)和4從上面的觸發器。

  2. 您將有可變g_global_variable包(從上面)

3行動:

1. in trigger for block 1 initiate g_global_variable 
2. in trigger for block 2 or 3, populate it with actual values 
3. in trigger for block 4, create your logic 

Ofcourse,g_global_variable可能並不孤單,它可以記錄或收藏。

+0

好吧,但我忘了指定我必須使用Oracle 10g ...在這種情況下,您看到解決方案嗎? – cooow

+0

在這種情況下沒有簡單的解決方案,所以一般的方法是切換到程序包/過程以插入/修改數據。但是有一個有限的解決方法(我會在答案中描述它) – vav