簡體   English   中英

Oracle觸發器 - 而不是刪除,更新行

[英]Oracle trigger- instead of delete, update the row

如何編寫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;

但我正在改變表錯誤。 這可能嗎?

如果確實需要觸發器,則更合乎邏輯的方法是創建視圖,在視圖上創建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;

更好的是,您可以省去觸發器,創建應用程序將調用的delete_item過程而不是發出DELETE並且該過程只是更新行以設置item_stat列而不是刪除行。

如果你真的,真的,真的想要一個涉及表本身觸發器的解決方案,你可以

  1. 創建一個包含成員的包,該成員是映射到m_item_h表中數據的記錄集合
  2. 創建清空此語句集合的前刪除語句級別觸發器
  3. 創建一個刪除行前級觸發器,它將:old.<<primary key>>和所有其他:old值插入到集合中
  4. 創建一個after delete語句級觸發器,它遍歷集合,將行重新插入表中,並設置item_stat列。

這將涉及更多的工作, instead of trigger因為你必須刪除然后重新插入行,它將涉及更多的移動件,所以它將不那么優雅。 但它會奏效。

首先,你編寫的觸發器會拋出一個變異表錯誤。 從技術上講,你所要求的是不可能的,即刪除不會刪除而是更新,除非你在中間引發一個異常,這可能是一種丑陋的方式。 我認為用戶使用某種應用程序前端允許他們使用刪除按鈕delete數據,因此您可以使用更新語句而不是delete語句。

另一種選擇是創建一個日志表,您可以在將記錄從實際表中刪除之前插入記錄,然后將日志表與實際表一起加入以檢索已刪除的記錄。 就像是-

 CRETAE TABLE M_ITEM_H_DEL_LOG as SELECT * FROM M_ITEM_H WHERE 1=2;

接着

create or replace
trigger DELFOUR.T4M_ITEM_ONDELETE
before delete on M_ITEM_H
FOR EACH ROW
BEGIN
  INSERT INTO
    M_ITEM_H_DEL_LOG
  VALUES (:old.col1, :old.col2,.....) --col1, col2...are columns in M_ITEM_H
  ;
END;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM