1

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

任何建议将不胜感激。

4

2 回答 2

2

实际上有一种方法可以做到这一点......

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

  1. 重命名表
  2. 使用原始名称在该表上创建一个视图
  3. 在视图上创建一个“代替”触发器,然后写入原始表
  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
    );
于 2016-12-09T14:32:59.533 回答
0

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

于 2013-04-01T17:41:05.300 回答