Выбор триггера из той же таблицы - PullRequest
2 голосов
/ 03 января 2012

Я хотел бы задать вопрос о триггерах.Допустим, у меня есть таблица T и мне нужен триггер перед обновлением.Однако у меня есть проблема.Мне нужно проверить условие, используя другие строки T из триггера.Мой вопрос: какая СУБД поддерживает это?Где я могу написать триггеры, которые выполняют выбор (ы) в той же таблице, где срабатывает триггер.Например:

CREATE TRIGGER updtrigger BEFORE UPDATE ON Employee
    -> FOR EACH ROW
    -> BEGIN
    -> IF NEW.Salary<=500 THEN
    -> SET NEW.Salary=10000;
    -> ELSEIF NEW.Salary>500 and NEW.Salary < 600 THEN
    -> SET NEW.Salary=15000;
    -> ELSEIF NEW.Salary > (select MAX(Salary) from Employee)
    -> Set NEW.Salary = 601;
    -> END IF;
    -> END
    -> //

Спасибо,

С уважением,

Лайос Арпад.

Ответы [ 2 ]

4 голосов
/ 04 января 2012

Например, данный триггер вызовет исключение Mutating table в Oracle, но в Oracle есть решение, например, этот триггер разрешен и работает нормально:

CREATE or replace TRIGGER updtrigger BEFORE UPDATE ON Employees
     FOR EACH ROW
DECLARE
 pragma autonomous_transaction;
 n number;
     BEGIN
     select MAX(Salary) into n from Employees;
     IF :NEW.Salary<=500 THEN
          DBMS_OUTPUT.PUT_LINE('kisebb mint 500');
          :NEW.salary:=n;
    end if;
commit;
     END;
0 голосов
/ 09 января 2019

Хотя использование автономных транзакций технически является способом избежать ORA-04091, я не рекомендую использовать его по двум причинам:

1.Автономная транзакция не может видеть незафиксированные изменения транзакции вызывающей стороны. Например, триггер, аналогичный приведенному выше решению, не дает правильного результата в следующем случае:

delete from employees;    
insert into employees (id, name, salary) values (1, 'A', 5000);
insert into employees (id, name, salary) values (2, 'B', 1000);
commit;
update employees set salary=800 where id=1;
update employees set salary=100 where id=2;
select * from employees;

Во время второго обновления оператор выбора в триггере не может увидеть результат первого обновления, он увидит исходное значение 5000, а не 800. Но, конечно, он может работать в некоторых случаях.

2.Другая причина избежать этого - только личное предложение. Если вы используете толстый клиент, я рекомендую создать хранимую процедуру update_salary, которая сначала проверяет бизнес-правила, вычисляет суммы, и, наконец, выдает команду update сотрудники .... Или, если вы создаете тонкий клиент или используете постоянный API-интерфейс, вы должны сделать это на сервере приложений (например, EJB). В обоих случаях код будет удобочитаемым и поддерживаемым.

...