Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle触发器在插入或更新另一个表时更新该表_Oracle_Triggers - Fatal编程技术网

Oracle触发器在插入或更新另一个表时更新该表

Oracle触发器在插入或更新另一个表时更新该表,oracle,triggers,Oracle,Triggers,我有两个表(主明细表)用于记录订单,我需要创建一个触发器,该触发器允许我使用“小计”字段中的小计和更新主表中的“总计”字段(与外键“ID\u ORDEN”相关的明细表),但我得到了一个错误的触发器 表: CREATE TABLE "ENCABEZADO_ORDEN" ("ID_ENCABEZADO" NUMBER(10,0), "NUMERO_ORDEN" NUMBER(10,0), "FECHA" DATE, "NOMBRE_CLIENTE" VARCH

我有两个表(主明细表)用于记录订单,我需要创建一个触发器,该触发器允许我使用“小计”字段中的小计和更新主表中的“总计”字段(与外键“ID\u ORDEN”相关的明细表),但我得到了一个错误的触发器

表:

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) 重命名表“ENCABEZADO_ORDEN”(即“ENCABEZADO_ORDEN_选项卡”)和2)禁用/删除“TOTAL_GENERAL”字段,然后3)创建原始名称为“ENCABEZADO_ORDEN”的视图,如下所示:

这将确保TOTAL_GENERAL始终正确(事实上,任何通过更新ENCABEZADO_ORDEN将其直接设置为其他值的操作都会立即导致语法错误)


如果性能是一个问题(即用户经常在ENCABEZADO\u ORDEN表中查询TOTAL\u GENERAL字段,查找DETALLE\u ORDEN中有大量详细记录的订单,导致Oracle重复获取和汇总大量小计)然后使用物化视图而不是基本视图。

尝试通过谷歌搜索ORA-04091,了解变异表以及如何消除此错误。祝你一切顺利。
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'
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;