For example, you create person table, then insert 2 rows into it as shown below.
CREATE TABLE person (
id INTEGER,
name VARCHAR(20)
);
INSERT INTO person (id, name)
VALUES (1, 'John'), (2, 'David');
Next, you create log table, then you insert the row whose num is 0 into log table as shown below:
CREATE TABLE log (
num INTEGER
);
INSERT INTO log (num) VALUES (0);
Now, you can create my_func() trigger function with RETURNS trigger and LANGUAGE plpgsql which increments num by 1 as shown below:
CREATE FUNCTION my_func() RETURNS trigger
AS $$
BEGIN
UPDATE log SET num = num + 1;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
Next, you create my_v view as shown below.
CREATE VIEW my_v AS
SELECT * FROM person;
Now, you can create my_t trigger which runs my_func() when UPDATE or DELETE operation is prevented on my_view for each row as shown below:
CREATE TRIGGER my_t INSTEAD OF UPDATE OR DELETE ON my_v
FOR EACH ROW EXECUTE FUNCTION my_func();
*Memos:
INSTEAD OF can prevent operations.
You can use INSTEAD OF only with a view and FOR EACH ROW otherwise there is error.
You cannot specify one or more columns with UPDATE OF when using INSTEAD OF otherwise there is error.
You cannot use TRUNCATE with INSTEAD OF otherwise there is error.
The trigger with BEFORE or AFTER and INSERT, UPDATE or DELETE on a view doesn't work. *My question and the answers explains it in detail.
Then, you insert a row to person table with my_v, then num is still 0 as shown below:
postgres=# INSERT INTO my_v (id, name) VALUES (3, 'Robert');
INSERT 0 1
postgres=# SELECT * FROM person;
id | name
----+--------
1 | John
2 | David
3 | Robert
(3 rows)
postgres=# SELECT num FROM log;
num
-----
0
(1 row)
Then, you try to update name to Tom on all 3 rows on person table with my_v, then the update is prevented, then num is 3 as shown below:
postgres=# UPDATE my_v SET name = 'Tom';
UPDATE 0
postgres=# SELECT * FROM person;
id | name
----+--------
1 | John
2 | David
3 | Robert
(3 rows)
postgres=# SELECT num FROM log;
num
-----
3
(1 row)
Then, you try to delete 2 rows from person table where id is 2 and 3 with my_v, then the deletion is prevented, then num is 5 as shown below:
postgres=# DELETE FROM my_v WHERE id IN (2, 3);
DELETE 0
postgres=# SELECT * FROM person;
id | name
----+--------
1 | John
2 | David
3 | Robert
(3 rows)
postgres=# SELECT num FROM log;
num
-----
5
(1 row)