Мутация в ORACLE BD

Я делаю БД с таблицами "Товары" и "Группы товаров". Я делаю различные триггеры для этих таблиц. У меня происходит мутация, в триггере UPDATE_C_RETAIL_MARKUP. Я не совсем понимаю, как можно ее исправить. Ошибка:

One error saving changes to table "USER1"."PRODUCT_GROUP":
Row 1: ORA-04091: таблица USER1.PRODUCT_GROUP изменяется, триггер/функция может не заметить это
ORA-06512: на  "USER1.UPDATE_C_RETAIL_MARKUP", line 2
ORA-04088: ошибка во время выполнения триггера 'USER1.UPDATE_C_RETAIL_MARKUP'
ORA-06512: на  "USER1.UPDATE_RETAIL_PRICES", line 3
ORA-04088: ошибка во время выполнения триггера 'USER1.UPDATE_RETAIL_PRICES'

Полный код :

  CREATE TABLE "USER1"."PRODUCT_GROUP" 
   (    "ID" NUMBER(*,0) DEFAULT "USER1"."GROUP_SEQUENCE"."NEXTVAL" NOT NULL ENABLE, 
    "NAME" VARCHAR2(80 BYTE) NOT NULL ENABLE, 
    "COUNT" NUMBER(*,0) DEFAULT 0, 
    "C_RETAIL" NUMBER DEFAULT 0, 
    "MARKUP" NUMBER DEFAULT 0 NOT NULL ENABLE, 
     CONSTRAINT "PRODUCT_GROUP_PK" PRIMARY KEY ("ID")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS"  ENABLE, 
     CONSTRAINT "PRODUCT_GROUP_CHK1" CHECK (markup >= 0 AND markup <= 1
) ENABLE
   ) SEGMENT CREATION IMMEDIATE 
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" ;

  CREATE OR REPLACE NONEDITIONABLE TRIGGER "USER1"."UPDATE_RETAIL_PRICES" 
AFTER UPDATE OF MARKUP ON product_group
FOR EACH ROW
BEGIN
  -- Обновляем розничные цены в таблице "Товары" для соответствующей группы
  UPDATE product
  SET retail_price = entry_price * (1 + :NEW.markup)
  WHERE group_id = :NEW.id;

END;
/
ALTER TRIGGER "USER1"."UPDATE_RETAIL_PRICES" ENABLE;

  CREATE OR REPLACE NONEDITIONABLE TRIGGER "USER1"."CASCADE_DELETE_PRODUCT_GROUP" 
BEFORE DELETE ON product_group
FOR EACH ROW
BEGIN
  -- Удаление связанных позиций из таблицы "Товары"
  DELETE FROM product WHERE group_id = :NEW.id;
END;
/
ALTER TRIGGER "USER1"."CASCADE_DELETE_PRODUCT_GROUP" ENABLE;


  CREATE TABLE "USER1"."PRODUCT" 
   (    "ID" NUMBER(*,0) DEFAULT "USER1"."PRODUCT_SEQUENCE"."NEXTVAL" NOT NULL ENABLE, 
    "NAME" VARCHAR2(80 BYTE) NOT NULL ENABLE, 
    "GROUP_ID" NUMBER(*,0) DEFAULT 0 NOT NULL ENABLE, 
    "ENTRY_PRICE" NUMBER DEFAULT 0, 
    "RETAIL_PRICE" NUMBER DEFAULT 0, 
    "COUNT" NUMBER(*,0) DEFAULT 0 NOT NULL ENABLE, 
     CONSTRAINT "PRODUCT_PK" PRIMARY KEY ("ID")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS"  ENABLE, 
     CONSTRAINT "PRODUCT_FK1" FOREIGN KEY ("GROUP_ID")
      REFERENCES "USER1"."PRODUCT_GROUP" ("ID") ENABLE
   ) SEGMENT CREATION IMMEDIATE 
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "USERS" ;

  CREATE OR REPLACE NONEDITIONABLE TRIGGER "USER1"."DELETE_GROUP_C_RETAIL" 
AFTER DELETE ON product
FOR EACH ROW
BEGIN
    UPDATE product_group
    SET c_retail = c_retail - (:OLD.retail_price * :OLD.count)
    WHERE id = :OLD.group_id;
END;
/
ALTER TRIGGER "USER1"."DELETE_GROUP_C_RETAIL" ENABLE;

  CREATE OR REPLACE NONEDITIONABLE TRIGGER "USER1"."UPDATE_RETAIL_PRICE" 
BEFORE INSERT OR UPDATE OF ENTRY_PRICE ON product
FOR EACH ROW
BEGIN
  DECLARE
    v_markup product_group.markup%TYPE;
  BEGIN
    -- Получаем наценку на группу товара
    SELECT markup
    INTO v_markup
    FROM product_group
    WHERE id = :NEW.group_id;

    -- Вычисляем розничную цену
    :NEW.retail_price := :NEW.entry_price * (1 + v_markup);
  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      -- Если группа товара не найдена
      :NEW.retail_price := 0;
  END;
END;
/
ALTER TRIGGER "USER1"."UPDATE_RETAIL_PRICE" ENABLE;

  CREATE OR REPLACE NONEDITIONABLE TRIGGER "USER1"."UPDATE_GROUP_COUNT" 
BEFORE INSERT OR UPDATE OF COUNT ON product
FOR EACH ROW
BEGIN
  -- Обновляем "COUNT" в группе товаров внутри блока транзакции
   IF UPDATING THEN
   UPDATE product_group  SET count = count-:OLD.count+:NEW.count WHERE id = :NEW.group_id;
   ELSE 
   UPDATE product_group  SET count = count+:NEW.count WHERE id = :NEW.group_id;
   END IF;
END;
/
ALTER TRIGGER "USER1"."UPDATE_GROUP_COUNT" ENABLE;

  CREATE OR REPLACE NONEDITIONABLE TRIGGER "USER1"."UPDATE_GROUP_COUNT_DELETE" 
AFTER DELETE ON product
FOR EACH ROW
BEGIN
  -- Уменьшаем "count" в группе товаров на значение "count" удаляемого товара

  UPDATE product_group
  SET count = CASE
                 WHEN count - :OLD.count < 0 THEN 0
                 ELSE count - :OLD.count
               END
  WHERE id = :OLD.group_id;
END;
/
ALTER TRIGGER "USER1"."UPDATE_GROUP_COUNT_DELETE" ENABLE;

  CREATE OR REPLACE NONEDITIONABLE TRIGGER "USER1"."INSERT_GROUP_C_RETAIL" 
AFTER INSERT ON product
FOR EACH ROW
BEGIN
    UPDATE product_group
    SET c_retail = c_retail + (:NEW.retail_price * :NEW.count)
    WHERE id = :NEW.group_id;
END;
/
ALTER TRIGGER "USER1"."INSERT_GROUP_C_RETAIL" ENABLE;

  CREATE OR REPLACE NONEDITIONABLE TRIGGER "USER1"."UPDATE_GROUP_C_RETAIL" 
AFTER UPDATE OF ENTRY_PRICE ON product
FOR EACH ROW
BEGIN
    UPDATE product_group
    SET c_retail = c_retail - (:OLD.retail_price * :NEW.count) + (:NEW.retail_price * :NEW.count)
    WHERE id = :NEW.group_id;
END;
/
ALTER TRIGGER "USER1"."UPDATE_GROUP_C_RETAIL" ENABLE;

  CREATE OR REPLACE NONEDITIONABLE TRIGGER "USER1"."UPDATE_C_RETAIL_MARKUP" 
BEFORE UPDATE OF RETAIL_PRICE ON product
FOR EACH ROW
BEGIN
  UPDATE product_group
  SET c_retail = :NEW.retail_price * :NEW.count
  WHERE id = :NEW.group_id;
END;
/
ALTER TRIGGER "USER1"."UPDATE_C_RETAIL_MARKUP" ENABLE;

Ответы (0 шт):