1

になったときに発生する次のトリガーがありupdatedますY。テーブルに値が存在しない場合にのみ、古い値を挿入したいと思いmy_histます。同じレコードが存在する場合は、挿入しないでください。この最善の方法は、my_histテーブルの一意性をチェックするための制約を作成するか、トリガーでこの条件をチェックするかです。もしそうなら、どうすればトリガーでこれを行うことができますか?

または、重複レコードを挿入しないように、トリガーで my_hist テーブルの一意の制約を確認することは可能ですか。

CREATE OR REPLACE TRIGGER mytrig
    AFTER UPDATE
    ON mytab
    FOR EACH ROW
WHEN (
new.updated = 'Y'
      )
BEGIN
    INSERT INTO my_hist
      VALUES   (
                        :old.id,
                        :old.no,                        
                        :old.start_date,
                        :old.end_date,
                        SYSDATE
                  );
END mytrig;
/
4

2 に答える 2

3

一意性を強制する場合は、一意制約を使用します。自分で何かをコーディングするよりも、常にそれが望ましいでしょう。

INSERT行がステートメントの一部として既に存在するかどうかを確認できます

INSERT INTO my_hist( id, 
                     no, 
                     start_date, 
                     end_date, 
                     some_other_column )
  SELECT :old.id, 
         :old.no, 
         :old.start_date,
         :old.end_date,
         sysdate
    FROM dual
   WHERE NOT EXISTS( SELECT 1
                       FROM my_hist
                      WHERE my_hist.id = :old.id
                        AND my_hist.no = :old.no
                        AND my_hist.start_date = :old.start_date
                        AND my_hist.end_date   = :old.end_date );

ただし、複数のセッションが同時に同じ行を挿入する可能性があるマルチユーザー環境では、これは機能しません。

于 2012-06-12T19:44:07.180 に答える
1

insert重複が既に存在するかどうかを確認するために、次のように変更できます。my_histselect は、主キーが と であるidと想定し、主キーの値が異なる場合にのみ使用するように句をstart_date変更しwhere not existsます。

insert into my_hist
select :old.id, :old.no, :old.start_date, :old.end_date, sysdate
  from dual
 where not exists ( select 1
                      from my_hist
                     where id = :old.id
                       and start_date = :old.start_date
                           )

ただし、これにはインデックス スキャンが必要なため、最適ではありません。

代わりに、例外を発生させます。明示的に名前が付けられています: dup_val_on_index. これが発生した場合は、単に無視してください。

BEGIN
    INSERT INTO my_hist
      VALUES   (
                        :old.id,
                        :old.no,                        
                        :old.start_date,
                        :old.end_date,
                        SYSDATE
                  );
-- ignore an exception that get's raised if a duplicate value
-- gets inserted. 
EXCEPTION WHEN DUP_VAL_ON_INDEX then null;
END mytrig;
于 2012-06-12T19:47:07.597 に答える