【问题标题】:POSTGRESQL Trigger that updates a column after having altered the table在更改表后更新列的 POSTGRESQL 触发器
【发布时间】:2020-12-30 10:56:19
【问题描述】:

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

是否可以通过触发器来实现它,以便在 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;

【问题讨论】:

  • 您确定您正在运行 MySQL 吗?这是 Postgres 语法。
  • @GMB 你是对的,我的错
  • 这将非常低效。 new_column 无论如何都不包含新信息,因此最好创建一个包含所有 mytable1 列以及 select count 子查询作为额外列的视图,而不是更改 mytable1 的结构。

标签: sql postgresql triggers sql-update alter-table


【解决方案1】:

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

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

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

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

至于您希望在触发器中使用的逻辑:您需要使用 newold 来引用原始表中更改的行 - 通常,您希望更新会影响 no行(如果 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 触发器,现在您还需要一个insertdelete 触发器)。相反,您可以在需要时动态计算逻辑,或创建视图:

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

【讨论】:

    【解决方案2】:

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

    流程是:

    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;
      

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

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

    【讨论】:

      猜你喜欢
      • 2017-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-25
      • 2021-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多