【问题标题】:Informix insert trigger: update value on same table but different recordInformix 插入触发器:更新同一张表上的值但不同的记录
【发布时间】:2013-03-18 01:19:24
【问题描述】:

有什么方法可以让插入触发器将同一表上不同记录中的值更新为插入的记录?据我了解,Informix 似乎不允许我这样做,因为它不允许您更新触发器所在的同一个表中的值。我已经看到建议您从存储过程返回值并在触发器中使用“into”语句,但我认为这个概念不适用于我的情况,因为更新需要在不同的记录上完成正在插入。

任何建议将不胜感激。

【问题讨论】:

  • 在 ids@iiug.org 邮件列表上也有人问过这个问题,并且一致认为没有办法做到这一点。我同意共识。
  • 谢谢 - 这是一个非常烦人的“功能”。

标签: triggers informix


【解决方案1】:

其实有办法做到这一点...

确实不能直接更新同一个表/列 触发,但有一个简单的解决方法,使用 视图和“代替”触发器一直对我有用。

  1. 重命名表格
  2. 使用原始名称在该表上创建一个视图
  3. 在视图上创建一个“instead of”触发器,然后写入原始表
  4. 通过撤销对原始表的所有权限来强制使用视图

这是所提出问题的真实示例 - 带有日期范围的价目表, 同一项目的其他行需要随时更新 完成插入、更新、删除,以避免有日期范围 重叠(同一日期有多个价格)。

价目表:

item    valid_from   valid_to       price
 01     2010-01-01   2013-03-15    120.00
 01     2013-04-16   2015-12-31    125.00
 01     2016-01-01   2016-05-05    130.00
 01     2016-05-06                 140.00

首先,将表替换为同名视图:

RENAME TABLE pricelist TO pricelist_table;
CREATE VIEW pricelist AS SELECT * FROM pricelist_table;
REVOKE ALL ON pricelist_table FROM public;
GRANT ALL ON pricelist TO public;

现在做一个插入触发器来更新同一张表的其他行 视图的基础(在此示例中是为了避免从/到日期重叠)。 通过兼顾视图和表名,您还可以避免关于 更新子查询中引用的表(触发器中的第二次更新)。

CREATE TRIGGER ins_pricelist INSTEAD OF INSERT ON pricelist
       REFERENCING new AS new
   FOR EACH ROW (

     -- write the data to the real table
     insert into pricelist_table
     values(new.item,new.valid_from,new.valid_to,new.price),

     -- close off the previous price row by setting its "valid_to" date
     update pricelist_table set valid_to = new.valid_from - 1
      where item = new.item and valid_from < new.valid_from
        and ( valid_to >= new.valid_from or valid_to is null ),

     -- if the row we're inserting has a null "valid_to" date,
     -- set it to the day before the next "valid_from" date
     update pricelist set valid_to =
          (select min(valid_from)-1 from pricelist_table
            where item = new.item and valid_from > new.valid_from)
      where item = new.item and valid_from = new.valid_from
        and valid_to is null
   );

在支持带有触发器引用的过程的更高版本 (11+) 上, 更好和更易于维护的方法是调用单独的存储过程 来自触发器:

CREATE PROCEDURE write_pricelist()
       REFERENCING old AS old  new AS new  FOR pricelist;

  -- do all your inserts, updates, etc to pricelist_table here ...

END PROCEDURE;

-- These triggers all call the same stored procedure (above).
CREATE TRIGGER ins_pricelist INSTEAD OF INSERT ON pricelist
    REFERENCING new AS new
    FOR EACH ROW (
      EXECUTE PROCEDURE write_pricelist() WITH TRIGGER REFERENCES
    );
CREATE TRIGGER upd_pricelist INSTEAD OF UPDATE ON pricelist
    REFERENCING new AS new old AS old
    FOR EACH ROW (
      EXECUTE PROCEDURE write_pricelist() WITH TRIGGER REFERENCES
    );
CREATE TRIGGER del_pricelist INSTEAD OF DELETE ON pricelist
    REFERENCING old AS old
    FOR EACH ROW (
      EXECUTE PROCEDURE write_pricelist() WITH TRIGGER REFERENCES
    );

【讨论】:

    【解决方案2】:

    这个问题是在ids@iiug.org 邮件列表上提出的,大家一致认为没有办法做到这一点——我同意这个共识。

    【讨论】:

      猜你喜欢
      • 2018-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-11
      • 1970-01-01
      • 2011-10-19
      • 1970-01-01
      相关资源
      最近更新 更多