如何在没有已知列的情况下为PostgreSQL视图编写通用更新触发器



我使用PostgreSQL视图来模拟一个遗留表,该表后来被拆分为两个独立的表,因此我们可以保持与一系列服务的向后兼容性。目标本质上是让这个视图透明地运行,就好像它是拆分前的原始表一样。使用INSTEAD OF INSERT触发器,我能够非常容易地处理插入到这两个表中的操作。

然而,我很难弄清楚如何编写INSTEAD OF UPDATE触发器,因为我不知道在任何一个请求中哪些列会被更改(我使用的是sequelize,所以我真的没有任何方法来控制请求的内容,它可能是SET,一列,也可能是所有请求(。我在网上发现的所有例子似乎都在更新已知字段(要么是与查询相关的某个元列,要么是知道更新的形状(。

CREATE FUNCTION update_legacy_table_trigger()
RETURNS trigger AS $$
BEGIN
UPDATE table_a SET ??? WHERE id = NEW.id;
UPDATE table_b SET ??? WHERE table_a_id = NEW.id; 
END;
$$ LANGUAGE plpgsql;

以下是一些示例案例:

想象一下:

  • legacy_table是视图的名称
  • table_a具有列:idnamedescriptiontypeshared_column
  • table_b具有列:idtable_a_id(table_a的外键(、priceshared_column

示例A:

UPDATE legacy_table SET name="Test", price="10.00" WHERE id="123";

我希望触发器的行为类似于:

UPDATE table_a SET name="Test" WHERE id="123";
UPDATE table_b SET price="10.00" WHERE table_a_id="123";

示例B:它还可以只接收一个表的更新

UPDATE legacy_table SET price="10.00" WHERE id="123";

因此,我们希望触发器的行为如下:

UPDATE table_b SET price="10.00" WHERE table_a_id="123";

示例C:一个请求中可能有很多列

UPDATE legacy_table SET name="Test", price="10.00", description="A test", type="foo", shared_column="bar" WHERE id="123";

因此触发器应该表现为:

UPDATE table_a SET name="Test", description="A test", type="foo", shared_column="bar" WHERE id="123";
UPDATE table_b SET price="10.00", shared_column="bar" WHERE table_a_id="123";

在某些情况下,可能需要对两个表进行更新,但我不认为在任何情况下,原始UPDATE中的列的名称与新表中的列名称有任何不同。

对于这些我不明确知道UPDATE查询是什么的情况,我该如何编写INSTEAD OF UPDATE触发器?

您必须为触发器函数中的所有列编写update语句。您的触发功能如下所示:

CREATE FUNCTION update_legacy_table_trigger()
RETURNS trigger AS $$
BEGIN
UPDATE table_a SET name=new.name, description=new.description,type=new.type, shared_column=new.shared_column WHERE id = NEW.id;
UPDATE table_b SET price=new.price, shared_columns=new.shared_columns WHERE table_a_id = NEW.id; 
return null;
END;
$$ 
LANGUAGE plpgsql;

你必须在你的视图上写下你的触发器如下:

CREATE TRIGGER trg_update_legacy 
INSTEAD OF UPDATE
ON legacy_table
FOR EACH ROW
EXECUTE PROCEDURE update_legacy_table_trigger();

演示

这将处理所有更新情况,因为NEW将包含更新的行,并且我们正在使用NEW行的数据更新所有字段。

最新更新