在更改 table 后更新列的 POSTGRESQL 触发器

POSTGRESQL Trigger that updates a column after having altered the table

我有一个已填充的 table,其中已经有一些特定的列。我想通过添加一个新列来更改 table 结构,该列将表示一个字段,该字段是另一个 table.

的行数

是否可以通过触发器来实现,以便在 alter 命令后自动执行? 我想出了类似的东西,但显然没有更新专栏:

触发器函数:

CREATE FUNCTION update_column() RETURNS TRIGGER AS
$BODY$
DECLARE
num INTEGER;
BEGIN
    SELECT COUNT(*) INTO num FROM mytable1, mytable2 WHERE mytable1.field = mytable2.field GROUP BY mytable1.field;
    UPDATE mytable1 SET new_column = num;
END;
$BODY$
LANGUAGE PLPGSQL;

触发器:

CREATE TRIGGER insert
AFTER UPDATE
ON mytable1
FOR EACH ROW
EXECUTE PROCEDURE update_column();

以及更改命令:

ALTER TABLE mytable1 ADD new_column INT;

Is it possible to implement it through a trigger in order to do it automatically after the alter command?

首先,您的触发器在 table 上的每个 update 之后触发,而不是在 alter table 之后触发。其次,无论如何触发此类 DDL 事件的意义不大。

如果您的 table 已经有数据,您可能需要在创建列后对其进行初始化,例如:

update mytable1 t1
set new_column = (select count(*) from mytable2 t2 where t2.field = t1.field)

至于触发器中您想要的逻辑:您需要使用 newold 来引用原始 table 中更改的行 - 通常,您会期望更新不会影响任何行(如果 field 未更改)或两行(如果它是):

update mytable1 t1
set new_column = (select count(*) from mytable2 t2 where t2.field = t1.field)
where t1.field in (new.field, old.field) and new.field <> old.field

也就是说,我不推荐这样的设置。维护此类派生信息既昂贵又乏味(您有一个 update 触发器,现在您还需要一个 insert 和一个 delete 触发器)。相反,您可以在需要时即时计算逻辑,或创建视图:

create view myview as
select t1.*, 
    (select count(*) from mytable2 t2 where t2.field = t1.field) as new_column
from mytable1 t1

您不会根据添加 列的时间在触发器中自动设置此值。当第二个 table.

发生变化时,您将使用触发器来维护该值

过程是:

  1. 添加具有默认值的列:

     alter table mytable1 add new_column int default 0;
    
  2. 将列的值初始化为当前值:

     update mytable1 t1
         set new_column = (select count(*) from mytable2 t2 where t2.field = t1.field);
    
  3. mytable2 上添加 insert/update/delete 个触发器。关键逻辑是:

     update mytable1
          set cnt = cnt + 1
          where t1.field = new.field;
    
     update mytable1
          set cnt = cnt - 1
          where t1.field = old.field;
    

如果您没有外键关系,如果 field 值不在 table 中,您可能还需要在 mytable1 中插入一行。但是,我强烈建议使用显式 foreign key 约束来防止这种情况发生。

这个 increments/decrements 对 进行更改时的值 table.