Mail.ruПочтаМой МирОдноклассникиВКонтактеИгрыЗнакомстваНовостиКалендарьОблакоЗаметкиВсе проекты

Мутации в триггерах ORACLE BD

Максим Лео Знаток (366), на голосовании 12 месяцев назад
Я делаю БД с таблицами "Товары" и "Группы товаров". У меня есть триггеры CASCADE_DELETE_PRODUCT_GROUP - для каскадного удаления группы вместе с ее товарами, DELETE_GROUP_C_RETAIL - обновление сводной стоимости группы при удалении товара, INSERT_GROUP_C_RETAIL - обновление сводной стоимости группы при добавлении товара, UPDATE_GROUP_C_RETAIL - обновление сводной стоимости группы при обновлении входной стоимости, UPDATE_GROUP_COUNT - обновление количества товаров в группе при добавлении товаров, изменении их количества или удалении, UPDATE_RETAIL_PRICE - рассчет розничной цены при добавлении товара или обновлении входной стоимости, UPDATE_RETAIL_PRICES - обновление розничных цен всех товаров в группе при изменении наценки.
Я хочу еще сделать триггер обновления сводной стоимости при изменении наценки:

 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;
Но возникает мутация:
 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'
Я пробовал добавить обновление сводной стоимости в UPDATE_RETAIL_PRICES, но тоже возникала мутация. Как правильно можно сделать триггер,чтобы не возникала мутация?

https://pastebin.com/PhD54Usm
Голосование за лучший ответ
bqlqmutoff Гуру (4529) 1 год назад
Возникновение мутации (ORA-04091) в вашем случае связано с тем, что вы пытаетесь изменить таблицу "product_group" внутри триггера "UPDATE_C_RETAIL_MARKUP", который уже вызывается из триггера "UPDATE_RETAIL_PRICES". Это создает циклическую зависимость, которая приводит к ошибке.

Чтобы избежать этой мутации, вы можете использовать переменные для сохранения значений и применять обновления после завершения основного обновления.
Максим ЛеоЗнаток (366) 1 год назад
а как он вызывается,если в UPDATE_C_RETAIL_MARKUP указано UPDATE OF RETAIL_PRICE, а в UPDATE_RETAIL_PRICES указано UPDATE OF MARKUP?
bqlqmutoff Гуру (4529) Максим Лео, Если в триггере `UPDATE_C_RETAIL_MARKUP` указано `UPDATE OF RETAIL_PRICE`, а в триггере `UPDATE_RETAIL_PRICES` указано `UPDATE OF MARKUP`, то вызов каждого из этих триггеров будет происходить при изменении соответствующих столбцов в таблице `product`. Триггер `UPDATE_C_RETAIL_MARKUP` будет вызываться каждый раз, когда происходит обновление столбца `RETAIL_PRICE` в таблице `product`. Триггер `UPDATE_RETAIL_PRICES` будет вызываться каждый раз, когда происходит обновление столбца `MARKUP` в таблице `product`. Таким образом, если вы хотите изменить наценку (`MARKUP`) и обновить сводную стоимость (`c_retail`) в группе товаров, вам нужно будет сначала обновить значение наценки, а затем изменить сводную стоимость в триггере `UPDATE_RETAIL_PRICES`.
Похожие вопросы