Everything just works from PG 9.3 onwards as noted by Jeff French... With some exceptions (more info below).
Simple example
You can test this code on your PostgreSQL. Use cascade drop when you are done (to drop view with the table).
-- create table
--DROP TABLE user_table CASCADE;
CREATE TABLE user_table (
id serial,
lastname varchar(100),
user_type varchar(2) DEFAULT 'nn',
PRIMARY KEY (id)
);
-- initial data
INSERT INTO user_table(lastname) VALUES('Foo');
SELECT * FROM user_table;
-- simple view (note, no id here)
CREATE OR REPLACE VIEW user_view
AS
SELECT lastname, user_type
FROM user_table
;
-- check view (will have initial data)
SELECT * FROM user_view;
-- insert into user_table via view
INSERT INTO user_view VALUES('Bar');
-- check (both will have both records)
SELECT * FROM user_view;
SELECT * FROM user_table;
-- you can run above many times
-- (id will auto-increment even though it is not in the view)
-- update user_table via view
UPDATE user_view SET user_type='v' WHERE lastname = 'Bar';
SELECT * FROM user_table;
Limitations
There are some limitations though and that will depend on you PG version.
- In PG 9.3 views cannot have any expressions etc. Also only one table is allowed... So more or less a simple select limiting, reordering, or renaming columns.
- In PG 9.4 views can be partially updatable. So you can have expression but you will not be able to update them (not out of the box at least).
If you have WHERE
in your view then you might get a bit weird results. So this will still work with insert:
CREATE OR REPLACE VIEW user_view
AS
SELECT lastname as last_name, user_type
FROM user_table
WHERE user_type = 'v'
;
INSERT INTO user_view VALUES('Bar');
But update might not work. At least this will not work in that it will update 0 rows:
UPDATE user_view SET user_type='v';
Because effectively that would be equivalent to below query (so makes sense if you think about it):
UPDATE user_view SET user_type='v' WHERE user_type = 'v';
I wonder if at some point they might support joins... But at the time of writing PG 14 is out and it doesn't support joined tabled in views (for updates I mean).
Alternatives
You can still use INSTEAD OF
triggers, especially for more complicated views. And you can use rules... But (as noted in the CREATE RULE docs) automatically updatable views will be faster then manually created rules.