2014-06-09 52 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