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)