2015-09-14 232 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詳細記錄單,引發甲骨文反覆取小計&和衆人),然後使用物化視圖,而不是基本的視圖。

相關問題