创建删除行的触发器
Create trigger that deletes rows
所以我有这个 table:
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 trigger:
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 procedure:
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.
我可以做些什么改变?或者尝试其他选项来做到这一点?
提前致谢!
你可能不能(或者至少你不应该)。
table 上的行级触发器通常无法在不导致变异 table 异常的情况下查询相同的 table。如果你真的下定决心,你可以创建一个包,在该包中创建一个 order_id
值的集合,创建一个初始化集合的 before 语句触发器,创建一个行级触发器,用 :new.order_id
,然后是遍历集合并调用 delete_order_row
的 after 语句触发器。然而,这需要处理很多动人的事情。对于将 quantity
设置为 0 的应用程序代码来说,删除该行通常更有意义。将逻辑放入删除应用程序刚刚插入(或更新)的行的触发器中通常会导致应用程序流程非常难以遵循(部分原因是您永远无法立即看到整个流程,您一直在寻找触发器正在产生什么副作用)和很难理解和调试的错误。
如果您决定使用触发器并且不想使用三触发器解决方案,您还可以重命名 table,创建一个名为 order_row
的视图,然后在视图上创建一个 instead of
触发器,根据 quantity
值。不过,这会为您的代码添加一个额外的间接层,而且它仍然会使应用程序流程难以遵循。
所以我有这个 table:
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 trigger:
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 procedure:
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.
我可以做些什么改变?或者尝试其他选项来做到这一点?
提前致谢!
你可能不能(或者至少你不应该)。
table 上的行级触发器通常无法在不导致变异 table 异常的情况下查询相同的 table。如果你真的下定决心,你可以创建一个包,在该包中创建一个 order_id
值的集合,创建一个初始化集合的 before 语句触发器,创建一个行级触发器,用 :new.order_id
,然后是遍历集合并调用 delete_order_row
的 after 语句触发器。然而,这需要处理很多动人的事情。对于将 quantity
设置为 0 的应用程序代码来说,删除该行通常更有意义。将逻辑放入删除应用程序刚刚插入(或更新)的行的触发器中通常会导致应用程序流程非常难以遵循(部分原因是您永远无法立即看到整个流程,您一直在寻找触发器正在产生什么副作用)和很难理解和调试的错误。
如果您决定使用触发器并且不想使用三触发器解决方案,您还可以重命名 table,创建一个名为 order_row
的视图,然后在视图上创建一个 instead of
触发器,根据 quantity
值。不过,这会为您的代码添加一个额外的间接层,而且它仍然会使应用程序流程难以遵循。