web-dev-qa-db-ja.com

別のテーブルの列が更新されたときに、あるテーブルの列を更新するトリガーを作成する

2つのテーブルがあります

注文(ID、日付、メモ)

そして

配信(ID、メモ、日付)

Orderで日付が更新されたときにDeliveryで日付を更新するトリガーを作成したい。

私は何かをすることを考えていました

CREATE OR REPLACE TRIGGER your_trigger_name
BEFORE UPDATE
ON Order
DECLARE
BEGIN
   UPDATE Delivery set date = ??? where id = ???
END;

日付と行のIDを取得するにはどうすればよいですか?

ありがとう

16
GigaPr

日付と行のIDを取得するにはどうすればよいですか?

これらがDELIVERY_DATEと呼ばれるORDERテーブルの列で、IDであるとすると、トリガーは次のようになります。

CREATE OR REPLACE TRIGGER your_trigger_name
    BEFORE UPDATE ON Order
    FOR EACH ROW 
BEGIN
   if :new.delivery_date != :old.delivery_date
   then
       UPDATE Delivery d
       set d.delivery_date = :new.delivery_date
       where d.order_id = :new.id;
    end if;
END;

FOR EACH ROW句に注意してください。これは、個々の行の値を参照するために必要です。 IFコンストラクトを使用して、配信時にUPDATEを実行するかどうかをテストしました。トリガーに他のロジックがない場合は、次のように書くことができます...

CREATE OR REPLACE TRIGGER your_trigger_name
    BEFORE UPDATE OF delivery_date ON Order
    FOR EACH ROW 
BEGIN
   UPDATE Delivery d
   set d.delivery_date = :new.delivery_date
   where d.order_id = :new.id;
END;

質問にお答えしましたが、余談ですが、データモデルが最適ではないことを指摘しておきます。適切に正規化された設計では、1つのテーブルのみにDELIVERY_DATEが保持されます。DELIVERYはそのための論理的な場所のようです。

17
APC

この種のトリガーが必要な場合は常に、設計をよく確認してください。本当に個別の配達記録が必要ですか?注文には実際に複数の配達がありますか?

トリガーは良いように見えますが、かなりすぐに混乱する傾向があります。

0
Rene

トリガーには次の形式の暗黙の新旧の参照がありますREFERENCING OLD AS OLD NEW AS NEW

:NEW値に書き込むことはできますが、:OLD値には書き込むことができません。

UPDATE Delivery set date = :new.delivery_date where id = :new.id;


CREATE OR REPLACE TRIGGER "BUR_TABLENAME" BEFORE
UPDATE ON "TABLE" FOR EACH ROW
BEGIN
  If :new.active_date is not null Then
    :new.active_date := TRUNC(:new.active_date);
End If;
END;

テンプレート:

CREATE OR REPLACE TRIGGER TRIGGER_NAME
 BEFORE
 UPDATE
 ON TABLE_NAME
 REFERENCING OLD AS OLD NEW AS NEW
 FOR EACH ROW
DECLARE
   V_VARIABLE   NUMBER (1);
BEGIN
   //Do Stuff;
  null;
end;
0
Brian

OLDおよびNEWバインド変数を使用します。 OLDは、変更が行われる前に更新される行または列を参照します。 NEWは変更後にそれを参照します。

CREATE OR REPLACE TRIGGER trig1
    BEFORE UPDATE
    ON order  REFERENCING NEW AS new
    FOR EACH ROW
BEGIN
    UPDATE delivery
       SET ddate   = :new.ddate
     WHERE id = :new.id;
END;

REFERENCING句を変更して、バインド変数に異なる名前を付けることができます。 OLD as <name>も含めることができます。例:

CREATE OR REPLACE TRIGGER trig1
    BEFORE UPDATE
    ON order REFERENCING OLD AS old_values NEW AS new_values
    ...

「古い」と「新しい」のデフォルト名を変更したくない場合は、REFERENCING句を完全に省略できます。

0
Igby Largeman