2015-09-14 175 views
-1

我有两个表(主 - 细节)用于记录命令,我需要创建一个触发器,允许我更新在其中的“TOTAL_GENERAL”字段主表与“SUBTOTAL”字段中的小计总和与外键“ID_ORDEN”相关的详细表中,但我得到触发器错误。当另一个表插入或更新时,Oracle触发器更新一个表

表:

CREATE TABLE "ENCABEZADO_ORDEN" 
    ("ID_ENCABEZADO" NUMBER(10,0), 
    "NUMERO_ORDEN" NUMBER(10,0), 
    "FECHA" DATE, 
    "NOMBRE_CLIENTE" VARCHAR2(50), 
    "DIRECCION" VARCHAR2(50), 
    "TOTAL_GENERAL" NUMBER(10,0), 
    "LUGAR_VENTA" VARCHAR2(50), 
    CONSTRAINT "ENCABEZADO_ORDEN_PK" PRIMARY KEY ("ID_ENCABEZADO") 
    USING INDEX ENABLE 
    ) 

CREATE TABLE "DETALLE_ORDEN" 
    ("ID_DETALLE" NUMBER(10,0), 
    "PRODUCTO" VARCHAR2(50), 
    "PRECIO_UNITARIO" NUMBER(10,2), 
    "CANTIDAD" NUMBER(10,0), 
    "SUBTOTAL" NUMBER(10,2), 
    "ID_ENCABEZADO" NUMBER(10,0), 
    CONSTRAINT "DETALLE_ORDEN_PK" PRIMARY KEY ("ID_DETALLE") 
    USING INDEX ENABLE 
    ) 
/
ALTER TABLE "DETALLE_ORDEN" ADD CONSTRAINT "DETALLE_ORDEN_FK" FOREIGN KEY ("ID_ENCABEZADO") 
     REFERENCES "ENCABEZADO_ORDEN" ("ID_ENCABEZADO") ENABLE 
/

触发:

create or replace TRIGGER "CALCULAR_TOTAL_GENERAL" 
    BEFORE INSERT OR UPDATE ON "DETALLE_ORDEN" 
    FOR EACH ROW 
DECLARE 
    V_ID_ENCABEZADO NUMBER(10,0); 
BEGIN 
    SELECT "ID_ENCABEZADO" 
    INTO V_ID_ENCABEZADO 
    FROM "ENCABEZADO_ORDEN" 
    WHERE "ID_ENCABEZADO" = :NEW."ID_ENCABEZADO"; 

    UPDATE "ENCABEZADO_ORDEN" 
    SET "TOTAL_GENERAL" = (SELECT SUM("SUBTOTAL") FROM "DETALLE_ORDEN" 
    WHERE "ID_ENCABEZADO" = V_ID_ENCABEZADO) 
    WHERE "ID_ENCABEZADO" = V_ID_ENCABEZADO; 
END; 

这是错误消息我收到的时候我插入或更新表 “DETALLE_ORDEN”:

1 error has occurred 
ORA-04091: table CARLOSM.DETALLE_ORDEN is mutating, trigger/function may not see it 
ORA-06512: at "CARLOSM.CALCULAR_TOTAL_GENERAL", line 9 
ORA-04088: error during execution of trigger 'CARLOSM.CALCULAR_TOTAL_GENERAL' 
+0

尝试使用Google搜索ORA-04091并了解变异表以及如何摆脱此错误。祝一切顺利。 – Utsav

回答

1

不要使用这种逻辑的触发器(就此而言,不要使用触发器;总会有更好的方法)。另外,请尽可能避免在基表中存储冗余信息。

远更好的设计,以最小的影响现有的代码是 1)重命名表“ENCABEZADO_ORDEN”(即“ENCABEZADO_ORDEN_TAB”)和2)禁止/降“TOTAL_GENERAL”字段,然后3)创建的图原来的名字“ENCABEZADO_ORDEN”为:

CREATE OR REPLACE VIEW ENCABEZADO_ORDEN AS 
SELECT O.*, (SELECT SUM(D.SUBTOTAL) FROM DETALLE_ORDEN D 
      WHERE D.ID_ENCABEZADO = O.ID_ENCABEZADO) TOTAL_GENERAL 
FROM ENCABEZADO_ORDEN_TAB O; 

这将确保TOTAL_GENERAL总是正确的(其实,任何的努力,通过ENCABEZADO_ORDEN的更新直接将其设置为其他值会导致立即语法错误)。

如果性能是一个问题(即用户经常查询的ENCABEZADO_ORDEN表TOTAL_GENERAL领域具有大量的DETALLE_ORDEN详细记录单,引发甲骨文反复取小计&和众人),然后使用物化视图,而不是基本的视图。

相关问题