创建一个触发器,当另一个表中的列更新时更新一个表上的列

Posted

技术标签:

【中文标题】创建一个触发器,当另一个表中的列更新时更新一个表上的列【英文标题】:Create a trigger that updates a column on one table when a column in another table is updated 【发布时间】:2011-02-10 07:25:28 【问题描述】:

我有两张桌子

订单(id, date, note)

交货(ID、备注、日期)

我想创建一个触发器,当订单中的日期更新时更新交货中的日期。

我正在考虑做类似的事情

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

如何获取日期和行 ID?

谢谢

【问题讨论】:

【参考方案1】:

触发器中有一个隐式的新旧引用,形式为: 新旧如新

您可以写入 :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;

【讨论】:

【参考方案2】:

使用 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 子句。

【讨论】:

【参考方案3】:

我如何获取日期和行 ID?

假设这些是您的 ORDER 表中名为 DELIVERY_DATE 的列,并且您的触发器的 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 on Delivery。如果您的触发器中没有其他逻辑,您可以这样写...

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;

我已经回答了您提出的问题,但顺便说一句,我会指出您的数据模型不是最佳的。一个适当规范化的设计将只在一个表上保存 DELIVERY_DATE:DELIVERY 似乎是它的合乎逻辑的地方。

【讨论】:

【参考方案4】:

只要需要这种触发器,请仔细查看您的设计。真的需要单独的交货记录吗?一个订单真的有超过 1 个交货吗?

触发器看起来不错,但它们确实会很快把事情搞砸。

【讨论】:

以上是关于创建一个触发器,当另一个表中的列更新时更新一个表上的列的主要内容,如果未能解决你的问题,请参考以下文章

Oracle更新触发器在同一个表上

插入后使用 SQL Server 触发器更新另一个表中的列

用另一个表上的值更新新添加的列

根据另一个表上的字段长度更新

在配置触发器时更新表中的列时出现错误

比较两个表上的列,如果它的列与 table2 中的列匹配,则更新 table1