Oracle触发器-更新而不是删除行

Loc*_*ock 3 sql oracle triggers

我如何编写一个Oracle触发器,而不是在用户删除某个记录时实际上并没有发生删除,而是对那些行执行更新并将记录的状态设置为“ D”?

我试过了:

create or replace
trigger DELFOUR.T4M_ITEM_ONDELETE
before delete on M_ITEM_H
FOR EACH ROW
BEGIN
  UPDATE
    M_ITEM_H
  SET
    ITEM_STAT = 'D'
  WHERE
    CUST_CODE = 'TEST'
    AND ITEM_CODE = 'GDAY'
  ;

  raise_application_error(-20000,'Cannot delete item');
END;
Run Code Online (Sandbox Code Playgroud)

但是我正在变异表错误。这可能吗?

Jus*_*ave 5

如果确实需要触发器,则更合乎逻辑的方法是创建视图,INSEAD OF DELETE在视图上创建触发器,并强制应用程序针对视图而不是针对基表发布其删除操作。

CREATE VIEW vw_m_item_h
AS
SELECT *
  FROM m_item_h;

CREATE OR REPLACE TRIGGER t4m_item_ondelete
  INSTEAD OF DELETE ON vw_m_item_h
  FOR EACH ROW
AS
BEGIN
  UPDATE m_item_h
     SET item_stat = 'D'
   WHERE <<primary key>> = :old.<<primary key>>;
END;
Run Code Online (Sandbox Code Playgroud)

更好的是,您无需使用触发器,delete_item而是创建一个应用程序将调用的过程,而不是发出a,DELETE并且该过程将仅更新行以设置item_stat列,而不是删除行。

如果您确实真的想要一个涉及表本身触发器的解决方案,则可以

  1. 使用成员创建一个包,该成员是映射到m_item_h表中数据的记录的集合
  2. 创建一个清空之前的声明级别的触发器来清空此集合
  3. 创建一个删除前行级触发器,将:old.<<primary key>>和其他所有:old值插入到集合中
  4. 创建一个after after语句级别的触发器,该触发器在集合中进行迭代,将行重新插入表中并设置item_stat列。

这将涉及比之更多的工作,instead of trigger因为您必须删除然后重新插入该行,并且会涉及更多的移动部件,因此它的美观程度将大大降低。但这会起作用。