3

ユーザーが特定のレコードを削除した場合、実際には削除は行われず、代わりにそれらの行が更新され、レコードのステータスが「D」に設定される場合よりも、Oracleトリガーを作成するにはどうすればよいですか。

私は試した:

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;

しかし、ミューティングテーブルエラーが発生しています。これは可能ですか?

4

2 に答える 2

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;

さらに良いことに、トリガーを省略し、delete_itemアプリケーションが発行するのではなく呼び出すプロシージャを作成し、そのプロシージャは、行を削除するのではなく、DELETE単に行を更新して列を設定します。item_stat

テーブル自体のトリガーを含むソリューションが本当に、本当に、本当に必要な場合は、次のことができます。

  1. m_item_hテーブル内のデータにマップするレコードのコレクションであるメンバーを含むパッケージを作成します
  2. このコレクションを空にするbeforedeleteステートメントレベルのトリガーを作成します
  3. :old.<<primary key>>およびその他すべての:old値をコレクションに挿入する、削除前の行レベルのトリガーを作成します
  4. コレクションを反復処理し、行をテーブルに再挿入し、列を設定する、削除後のステートメントレベルのトリガーを作成しitem_statます。

これには、行を削除してから再挿入する必要があるため、より多くの作業が必要になりinstead of triggerます。また、移動するピースがはるかに多くなるため、エレガントさが大幅に低下します。しかし、それはうまくいくでしょう。

于 2012-09-05T02:20:09.227 に答える
4

まず最初に、作成したトリガーは変更テーブルエラーをスローします。技術的には、あなたが求めていることは不可能です。つまり、途中で例外を発生させない限り、削除は削除されずに更新されます。これは、醜い方法である可能性があります。deleteユーザーは、削除ボタンを使用してデータを取得できる、ある種のアプリケーションフロントエンドを使用していると思います。そのため、ステートメントの代わりに更新ステートメントを使用できますdelete

もう1つのオプションは、ログテーブルを作成することです。この場合、レコードを実際のテーブルから削除する前に挿入し、ログテーブルを実際のテーブルと結合して削除されたレコードを取得できます。何かのようなもの-

 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;
于 2012-09-05T02:17:34.963 に答える