我创建的,如下图:
table
称为 person
table
称为 log
,其中插入了 1 行。view
称为 my_v
trigger function
称为 my_func()
,其目的是将 num.log
增加 1
。trigger
的 my_t
,在 my_func()
上执行 before
each statement
INSERT
(UPDATE
、DELETE
或 my_v
)。CREATE TABLE person (
name VARCHAR(20)
);
CREATE TABLE log (
num INTEGER
);
INSERT INTO log (num) VALUES (0);
CREATE VIEW my_v AS
SELECT * FROM person;
CREATE FUNCTION my_func() RETURNS trigger
AS $$
BEGIN
UPDATE log SET num = num + 1;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER my_t BEFORE INSERT OR UPDATE OR DELETE ON my_v
FOR EACH STATEMENT EXECUTE FUNCTION my_func();
为了更好地衡量,我还测试了
trigger
my_t
何时执行 after
each statement
CREATE TRIGGER my_t AFTER INSERT OR UPDATE OR DELETE ON my_v
FOR EACH STATEMENT EXECUTE FUNCTION my_func();
通过此设置,表
num
中 log
的值预计将计算触发器调用 my_func()
的次数。
在
my_v
中插入、更新或删除行时,log.num
保持为 0
。请参阅下面的陈述,其中最后一项是表中的检查log
(实际上在每个操作后进行了测试,但从此处删除以缩短问题):
postgres=# INSERT INTO my_v (name) VALUES ('John');
INSERT 0 1 /* -> 1 row successfully inserted */
postgres=# UPDATE my_v SET name = 'Tom';
UPDATE 1 /* -> 1 row successfully updated */
postgres=# DELETE FROM my_v;
DELETE 1 /* -> 1 row successfully deleted */
postgres=# SELECT num FROM log;
num
-----
0
(1 row)
因此,视图上带有
BEFORE
或 AFTER
和 INSERT
、UPDATE
或 DELETE
的触发器在 PostgreSQL 中不起作用。
重要:
my_t
触发器的替代版本与INSTEAD OF
和FOR EACH ROW
确实可以正常工作:
CREATE TRIGGER my_t INSTEAD OF INSERT OR UPDATE OR DELETE ON my_v
FOR EACH ROW EXECUTE FUNCTION my_func();
如何创建
my_t
触发器,在每个语句的 my_func()
上发生 INSERT
、UPDATE
或 DELETE
操作之前或之后触发 my_v
?
PostgreSQL 上的行级触发器不支持 Before 或 After
39.1。触发器行为概述
行级 BEFORE 触发器在对特定行进行操作之前立即触发,而行级 AFTER 触发器在语句末尾(但在任何语句级 AFTER 触发器之前)触发。 这些类型的触发器只能在表和外部表上定义,不能在视图上定义。INSTEAD OF 触发器只能在视图上定义,并且只能在行级别;当视图中的每一行被识别为需要操作时,它们会立即触发。
事实上 INSTEAD OF 触发器只能在视图上定义。
要么在底层table上设置before触发器,要么使用INSTEAD OF触发器并将逻辑放入其中and,然后对底层表执行操作。