Создать триггер, который удаляет строки
Итак, у меня есть эта таблица:
CREATE TABLE orders_rows (
order_id NUMBER(10) PRIMARY KEY,
row_num DATE NOT NULL,
p_id NUMBER(10) NOT NULL,
quantity NUMBER(10) NOT NULL,
);
И я хочу создать триггер, который при обновлении меняет количество на 0 (ноль) -> удалить эту строку.
Я попробовал это:
Триггер CHECK_ORDER_ROW:
create or replace
TRIGGER check_order_row
AFTER INSERT OR UPDATE on orders_rows
for each row
BEGIN
if :new.quantity = 0 then
DELETE_ORDER_ROW(:new.order_id, :new.row_num);
end if;
END;
DELETE_ORDER_ROW - это процедура:
Процедура DELETE_ORDER_ROW:
create or replace
PROCEDURE delete_order_row (p_order_id NUMBER, p_row_num NUMBER)
IS
BEGIN
DELETE orders_rows WHERE (order_id = p_order_id and row_num = p_row_num);
COMMIT;
END;
Но когда я пытаюсь обновить:
update orders_rows set quantity=0 where (order_id=1 and row_num=1);
Я получаю ошибку:
A trigger (or a user defined plsql function that is referenced in
this statement) attempted to look at (or modify) a table that was
in the middle of being modified by the statement which fired it.
Любые изменения я могу сделать? Или попробуйте другие варианты сделать это?
Заранее спасибо!
1 ответ
Вы, вероятно, не можете (или, по крайней мере, не должны).
Триггер уровня строки в таблице обычно не может запрашивать эту же таблицу, не вызывая исключение изменяющейся таблицы. Если бы вы были действительно настроены, вы могли бы создать пакет, создать коллекцию order_id
значения в этом пакете, создайте триггер оператора before, который инициализирует коллекцию, создайте триггер на уровне строк, который заполнил коллекцию :new.order_id
, а затем триггер оператора после, который перебрал коллекцию и вызвал delete_order_row
, Это, однако, много движущихся частей, чтобы иметь дело с. Как правило, для кода приложения, который устанавливает quantity
до 0, чтобы удалить строку вместо. Помещение логики в триггер, который удаляет строку, которую только что вставленное (или обновленное) приложение обычно приводит к потокам приложений, за которыми очень трудно следить (отчасти потому, что вы никогда не видите весь поток сразу, вы постоянно хотите видеть какие триггеры побочных эффектов создают) и ошибки, которые очень трудно понять и отладить.
Если вы решили использовать триггер и не хотите использовать решение с тремя триггерами, вы также можете переименовать таблицу, создать представление с именем order_row
и создать instead of
вызвать вид, который превратился update
на вид в update
или delete
на базовом столе в зависимости от quantity
значение. Это добавляет дополнительный уровень косвенности к вашему коду, и все же имеет тенденцию усложнять отслеживание потоков приложений.