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

标签 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;

但是我遇到了变异表错误。这可能吗?

最佳答案

如果你真的需要一个触发器,更合乎逻辑的方法是创建一个 View ,创建一个 INSEAD OF DELETE在 View 上触发,并强制应用程序针对 View 而不是针对基表执行删除操作。

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;

更好的是,您可以省去触发器,创建一个 delete_item您的应用程序将调用而不是发出 DELETE 的过程并且该过程将简单地更新该行以设置 item_stat列而不是删除行。

如果你真的、真的、真的想要一个涉及到表本身的触发器的解决方案,你可以

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

这将比 instead of trigger 涉及更多的工作。因为你必须删除然后重新插入该行,它会涉及更多的移动部分,所以它会不那么优雅。但它会起作用。

关于sql - Oracle 触发器——更新行而不是删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12273564/

相关文章:

sql - 给定一列有效日期,是否有 SQL 语句可以将其转换为日期范围?

oracle - Tomcat session 复制:java.io.NotSerializableException : oracle. jdbc.driver.T4CConnection

php - MySQL 规模问题 - 触发器/更新/监控表

sql - 删除权重超过限制的行,直到没有这样的行

sql - 如何优化包含子查询的 MySQL 查询?

sql - 如何根据另一列的分位数将新列插入标签为“1”/“2”/“3”/“4”#的数据库中?

java - 如何在JSP中显示oracle(10g)查询结果?

SQL-约束

javascript - 如何让元素触发一个接一个地出现,间隔很小?

MySQL死锁问题