PostgreSQL中的TRIGGER ON VIEW不起作用

6

我正在尝试在PostgreSQL 9.6中的一个VIEW上添加触发器。

这是我的视图:

CREATE VIEW names AS
SELECT one.name AS name_one, two.name AS name_two, three.name AS name_three
FROM table_one one
LEFT JOIN table_two two ON one.id = two.id
LEFT JOIN table_three three ON two.id = three.id;

这是我的触发函数:
CREATE OR REPLACE FUNCTION notify_name_changed() RETURNS trigger AS $BODY$
  BEGIN
    PERFORM pg_notify('name_changed', row_to_json(NEW)::text);
    RETURN NULL;
  END; 
$BODY$ LANGUAGE plpgsql;

我的CREATE TRIGGER如下:
CREATE TRIGGER notify_name_changed INSTEAD OF INSERT OR UPDATE OR DELETE ON "names"
  FOR EACH ROW EXECUTE PROCEDURE notify_name_changed();

当基础表中的某些事件发生时,这不会触发任何更改。 然而,创建3个单独的触发器可以实现,但与视图有点无关:

CREATE TRIGGER notify_name_changed AFTER INSERT OR UPDATE OR DELETE ON "one"
  FOR EACH ROW EXECUTE PROCEDURE notify_name_changed();

CREATE TRIGGER notify_name_changed AFTER INSERT OR UPDATE OR DELETE ON "two"
  FOR EACH ROW EXECUTE PROCEDURE notify_name_changed();

CREATE TRIGGER notify_name_changed AFTER INSERT OR UPDATE OR DELETE ON "three"
  FOR EACH ROW EXECUTE PROCEDURE notify_name_changed();

是否可以直接在视图上添加触发器,在基础表发生任何更改时触发?

该文涉及IT技术。

一个instead of触发器会在你插入到视图时触发,而不是在你插入到其中一个基本表时触发。 - user330315
如果我直接在视图中进行插入操作,那么这是否会破坏视图与基本表之间的关系,并且从某种程度上删除了视图的概念? - Alfred Balle
在问题中我不清楚 - 当你说视图触发器没有触发时,你是否实际上正在视图上执行插入操作? - 404
不,我正在一个基本表中执行“插入”操作。 - Alfred Balle
1个回答

2
我认为您误解了视图的概念。
视图不保存任何数据,可以将其视为具有名称的“结晶化SQL语句”。每当在查询中使用视图时,它都会在“查询重写”步骤中被替换为其定义。
对于视图上的UPDATE操作,仅当您更新视图本身而不是基础表时,才会触发INSTEAD OF触发器。对于此,您需要在这些表上定义触发器。
您可能忽略的要点是,如果基础表中的内容发生变化,视图中的内容也会立即发生变化,因为视图只是基础表上的查询。

我同意,这很有道理。我的目标是能够在“视图”上(某种程度上)“监听”其基础表格中所做的任何更改。而不是在每个单独的基础表格上进行监听,因为这样会使自动查找“视图”中所做的更改变得更加困难,而这正是我所需要的。 - Alfred Balle
视图永远不会改变 - 它没有内容。 - Laurenz Albe
有道理,是的。谢谢。 - Alfred Balle
我认为应该支持:在视图上,可以定义触发器来代替执行INSERT、UPDATE或DELETE操作。这些INSTEAD OF触发器会针对需要在视图中修改的每一行触发一次。请参阅触发器行为概述 - Sergiu Indrie
@SergiuIndrie 当然可以,但我不明白你的意思。这并不意味着当基础表更改时,视图上的触发器会触发。 - Laurenz Albe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接