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

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

Максим Лео Знаток (365), на голосовании 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
Голосование за лучший ответ
Sergio 2.1 Оракул (67269) 1 год назад
Чтобы исправить ошибку мутации, вы можете использовать составной триггер, если вы используете Oracle 11g и более поздние версии. Вот пример:
 CREATE OR REPLACE TRIGGER customers_credit_policy_trg 
FOR UPDATE OR INSERT ON customers
COMPOUND TRIGGER
TYPE r_customers_type IS RECORD (
customer_id customers.customer_id% TYPE,
credit_limit customers.credit_limit% TYPE
);
TYPE t_customers_type IS TABLE OF r_customers_type INDEX BY PLS_INTEGER;
t_customer t_customers_type;
AFTER EACH ROW IS
BEGIN
t_customer (t_customer.COUNT + 1 ).customer_id := :NEW.customer_id;
t_customer (t_customer.COUNT).credit_limit := :NEW.credit_limit;
END AFTER EACH ROW;
AFTER STATEMENT IS
l_max_credit customers.credit_limit%TYPE;
BEGIN
SELECT MIN (credit_limit) * 5 INTO l_max_credit FROM customers WHERE credit_limit > 0 ;
FOR indx IN 1 .. t_customer.COUNT LOOP
IF l_max_credit < t_customer (indx).credit_limit THEN
UPDATE customers SET credit_limit = l_max_credit WHERE customer_id = t_customer (indx).customer_id;
END IF;
END LOOP;
END AFTER STATEMENT;
END;
ZГуру (2968) 1 год назад
Эбанутый с другого аккаунта начал ползать. Сколько их у тебя, и в каком ты старший)))
Максим ЛеоЗнаток (365) 1 год назад
Что здесь происходит вообще?
Похожие вопросы