2014-09-18 2 views
0

У меня есть две таблицы2 спусковые запуск Sametime

user_salary

------------------------- 
| user_id | salary_p | 
------------------------- 
| 1  | 100 | 
| 2  | 200 | 
------------------------- 

user_p_salary

------------------------ 
| user_id | salary_c | 
------------------------- 
| 1  | 100 | 
| 2  | 200 | 
------------------------- 

user_salary используется через пользовательский интерфейс, и имеет следующие триггером:

create or replace trigger t$user_salary_aiu 
    after insert or update of salary_p 
    on user_salary 
    for each row 
begin 
    update user_p_salary t 
    set t.salary_c = :new.salary_p, 
    where t.user_id = :new.user_id 
end t$user_salary_aiu; 

user_p_salary g ЭТС данные через интеграцию и имеет следующий код:

create or replace trigger t$user_p_salary_aiu 
    after insert or update of salary_c 
    on user_p_salary 
    for each row 
begin 
    update user_salary t 
    set t.salary_p = :new.salary_c, 
    where t.user_id = :new.user_id 
end t$user_p_salary_aiu;  

Теперь проблема заключается в том, что если одна из таблицы получает данные, то он выполняет свои триггерные и обновляет данные в другой таблице. Однако также запускается триггер в другой таблице, который похож на цикл триггера.

Единственный способ - использовать немедленный «alter triggername disable», но это, похоже, вообще не работает в триггерах. Есть идеи?

Заранее спасибо :-)

+0

Я довольно удивлен, что вы не получаете ошибку ORA-04091. Вы используете автономные транзакции? –

+0

Да, я получаю ошибку ORA-04901 – Jaanna

ответ

1

Почему не только обновлять зарплату, если она не равна новому значению, например.

create or replace trigger t$user_salary_aiu 
    after insert or update of salary_p 
    on user_salary 
    for each row 
begin 
    update user_p_salary t 
    set t.salary_c = :new.salary_p 
    where t.user_id = :new.user_id 
    and ( t.salary_c <> :new.salary_p 
     or (t.salary_c is null and :new.salary_p is not null) 
     or (t.salary_c is not null and :new.salary_p is null)); 
end t$user_salary_aiu; 

create or replace trigger t$user_p_salary_aiu 
    after insert or update of salary_c 
    on user_p_salary 
    for each row 
begin 
    update user_salary t 
    set t.salary_p = :new.salary_c 
    where t.user_id = :new.user_id 
    and ( t.salary_p <> :new.salary_c; 
     or (t.salary_p is null and :new.salary_c is not null) 
     or (t.salary_p is not null and :new.salary_c is null)); 
end t$user_p_salary_aiu; 

Примечания: Несмотря на формулировку документации dml_event_clause update of column по-видимому, означает, что триггер будет срабатывать, если столбец включается в инициировании UPDATE заявления, т.е. если столбец обновляется, даже если она обновляется с тем же значением что это было.

1

Как насчет вас добавить столбец каждой таблицы называется BY_TRIGGER.

Для обновления или вставки вне вашего триггера вы просто не указываете этот столбец. Однако при обновлении или вставке из вашего триггера вы передаете значение 1.

Кроме того, в каждом триггере вы проверяете, является ли: new.BY_TRIGGER равно 1, и если это так, вы пропускаете вставку/обновление, чтобы другой стол.

2

Ошибка ORA-04091 - это именно то, что должно произойти здесь. Проще говоря, вы не можете делать то, что вы пытаетесь сделать. Подумайте об этом - вы обновляете таблицу №1, затем триггер на таблице №1 обновляет таблицу # 2, чья триггер обновляет таблицу №1, чей триггер обновляет таблицу № 2, снова и снова. Это триггерный цикл, и Oracle этого не позволяет. Правило состоит в том, что триггер строки не может получить доступ к таблице, которая уже была изменена (или «мутирована») в той же транзакции. Существуют методы (особенно сложные триггеры), которые позволяют вам «обходить» это, но лучшим подходом было бы переработать дизайн, чтобы устранить эту проблему. Извините, что являюсь плохими новостями. Удачи.