Creating and Using Views
1. Creating View
CREATE VIEW active_customers AS
SELECT id, full_name, email FROM customers WHERE status = 'active';
2. Creating View with Column List
CREATE VIEW customer_summary(id, name, total_orders) AS
SELECT c.id, c.full_name, count(o.id)
FROM customers c LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.id, c.full_name;
3. Querying Views
SELECT * FROM active_customers WHERE email LIKE '%@example.com';
| Behavior | Detail |
|---|---|
| Inlined | Planner expands view at query time |
| No cache | Materialized view if caching needed |
4. Creating Updatable Views
| Auto-Updatable If | Detail |
|---|---|
| Single base table | FROM clause |
| No GROUP/DISTINCT | Simple SELECT only |
| No set ops | No UNION/INTERSECT/EXCEPT |
| No window functions |
CREATE VIEW open_orders AS
SELECT id, customer_id, status, total_cents FROM orders WHERE status <> 'cancelled';
UPDATE open_orders SET status='shipped' WHERE id = 1001;
5. Using CHECK OPTION
CREATE VIEW us_customers AS
SELECT * FROM customers WHERE country = 'US'
WITH CASCADED CHECK OPTION;
-- inserts/updates that don't satisfy country='US' will fail
6. Creating Recursive Views
CREATE RECURSIVE VIEW org(id, name, depth) AS
SELECT id, name, 1 FROM employees WHERE manager_id IS NULL
UNION ALL
SELECT e.id, e.name, o.depth+1
FROM employees e JOIN org o ON e.manager_id = o.id;
7. Replacing View
CREATE OR REPLACE VIEW active_customers AS
SELECT id, full_name, email, country FROM customers WHERE status='active';
Note: OR REPLACE only allows ADDING columns at the end; existing ones cannot change type or be removed.
8. Altering View
ALTER VIEW active_customers ALTER COLUMN email SET DEFAULT '';
ALTER VIEW active_customers OWNER TO app_owner;
ALTER VIEW active_customers SET SCHEMA reporting;
9. Renaming View
ALTER VIEW active_customers RENAME TO active_customer_v;
10. Listing Views
\dv
SELECT table_schema, table_name FROM information_schema.views;
11. Dropping View
DROP VIEW IF EXISTS active_customers CASCADE;
12. Using Security Barrier Views
CREATE VIEW my_orders WITH (security_barrier=true) AS
SELECT * FROM orders WHERE customer_id = current_setting('app.user_id')::int;
Warning: Without
security_barrier, malicious user-supplied functions in outer WHERE can leak rows by short-circuiting evaluation.