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';
BehaviorDetail
InlinedPlanner expands view at query time
No cacheMaterialized view if caching needed

4. Creating Updatable Views

Auto-Updatable IfDetail
Single base tableFROM clause
No GROUP/DISTINCTSimple SELECT only
No set opsNo 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.