微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决在更改表后更新列的 POSTGRESQL 触发器

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

是否可以通过触发器实现它以便在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命令:

ALTER TABLE mytable1 ADD new_column INT;

解决方法

是否可以通过触发器实现它以便在alter命令之后自动执行?

首先,您的触发器在表中的每个 update 之后触发,而不是在 alter table 之后触发。其次,无论如何触发这样的 DDL 事件也没多大意义。

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

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

至于您在触发器中想要的逻辑:您需要使用 newold 来引用原始表中更改的行 - 通常,您会期望更新不影响任何行(如果 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
,

您不会根据添加列的时间在触发器中自动设置此值。当第二个表发生更改时,您将使用触发器来维护该值。

流程是:

  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 上添加插入/更新/删除触发器。关键逻辑是:

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

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

当对第二个表进行更改时,这会增加/减少值。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。