Простая ситуация когда вешаем тригер на вставку данных в таблицу и в этом триггере определяем надо ли вставлять эти данные или нет. В случае с MySQL всё оказалось не просто.
Проблема в том, что отменить запрос в триггере MySQL тривиальным образом нельзя. В той же MS SQL Server есть триггеры INSTEAD OF и достаточно просто прописать в триггере ROLLBACK
, что бы отменить вставку, но в MySQL команды транзакций использовать в триггерах нельзя.
Можно ли триггером в MySQL корректно отменить запись строки в базу? Нужен триггер запрещающий вставку. Есть несколько способов решения этой проблемы.
Вызов ошибки в триггере
Вызвав ошибку в триггере можно отменить выполнение запроса вызвавшего триггер.
К сожалению, в триггерах MySQL сейчас нет возможности корректно откатить транзакцию.
Самое лучшее (несмотря на то, что оно ужасно) решение сейчас — сделать какую-то ошибку.
Например, так:
create trigger bi_a before insert on a for each row insert into you_cannot_insert_into_this_table_because_of_the_trigger_check values ();
Табличка с длинным названием, конечно, не должна существовать. Выглядит как костыль, костыль и есть.
Удаление текущего потока
Триггер: Before Insert, Before Update, Before Delete.
IF THEN KILL QUERY CONNECTION_ID(); END IF;
Вызов процедуры из триггера
триггер before insert — OLD в нем нет. Если ничего не нужно делать — RETURN null;
begin; drop table a, b cascade; drop function if exists tgf_b_bi () cascade; create table a (id serial primary key, v varchar); create table b (id serial primary key, a_id integer, v varchar, constraint fk_b_a_id foreign key (a_id) references a(id)); create or replace function tgf_b_bi () returns trigger as $$ begin if not exists(select id from a where id = new.a_id) then return null; else return new; end if; end $$ language plpgsql; create trigger tg_a_bi before insert on b for each row execute procedure tgf_b_bi(); insert into a values (default, '1') ; insert into b values (default, 1, '1') ; insert into b values (default, 2, '2') ; rollback;
Такие дела в общем.