PostgreSQL Views

Create virtual tables from query results

👁️ What are Views?

Views are virtual tables created from SQL queries. They don't store data themselves but provide a saved query that you can treat like a table, simplifying complex queries and enhancing security.


-- Basic view syntax
CREATE VIEW view_name AS
SELECT column1, column2
FROM table_name
WHERE condition;
                                    

Key View Concepts

🔍

Virtual Table

Query results as a table

SELECT * FROM view_name
🔒

Security

Hide sensitive columns

-- Expose only safe data
♻️

Reusability

Save complex queries

-- Use view multiple times
📊

Simplification

Abstract complexity

-- Hide JOIN complexity

🔹 Creating Simple Views

Views act as saved queries that you can reference like regular tables. They're perfect for simplifying repetitive queries and providing consistent data access patterns across your application.

-- Create sample tables
CREATE TABLE customers (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    email VARCHAR(100),
    country VARCHAR(50)
);

CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    customer_id INTEGER REFERENCES customers(id),
    amount DECIMAL(10,2),
    order_date DATE
);

-- Insert sample data
INSERT INTO customers (name, email, country) VALUES
    ('John Doe', '[email protected]', 'USA'),
    ('Jane Smith', '[email protected]', 'UK');

INSERT INTO orders (customer_id, amount, order_date) VALUES
    (1, 150.00, '2024-01-15'),
    (1, 200.00, '2024-02-20'),
    (2, 300.00, '2024-01-10');

-- Create a simple view
CREATE VIEW customer_orders AS
SELECT 
    c.name,
    c.email,
    o.amount,
    o.order_date
FROM customers c
JOIN orders o ON c.id = o.customer_id;

-- Query the view
SELECT * FROM customer_orders;

Result:

name       | email              | amount  | order_date
-----------+--------------------+---------+------------
John Doe   | [email protected]   | 150.00  | 2024-01-15
John Doe   | [email protected]   | 200.00  | 2024-02-20
Jane Smith | [email protected]   | 300.00  | 2024-01-10

🔹 Views with Aggregations

Views can contain aggregate functions and GROUP BY clauses to create summary reports. These views provide pre-calculated statistics that are always up-to-date when queried.

-- Create view with aggregations
CREATE VIEW customer_summary AS
SELECT 
    c.id,
    c.name,
    COUNT(o.id) AS total_orders,
    SUM(o.amount) AS total_spent,
    AVG(o.amount) AS avg_order_value
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
GROUP BY c.id, c.name;

-- Query the summary view
SELECT * FROM customer_summary
ORDER BY total_spent DESC;

Result:

id | name       | total_orders | total_spent | avg_order_value
---+------------+--------------+-------------+-----------------
 1 | John Doe   | 2            | 350.00      | 175.00
 2 | Jane Smith | 1            | 300.00      | 300.00

🔹 Updatable Views

Simple views that select from a single table without aggregations can be updated directly. PostgreSQL automatically translates INSERT, UPDATE, and DELETE operations on the view to the underlying table.

-- Create updatable view
CREATE VIEW usa_customers AS
SELECT id, name, email
FROM customers
WHERE country = 'USA';

-- Insert through view
INSERT INTO usa_customers (name, email)
VALUES ('Bob Wilson', '[email protected]');

-- Update through view
UPDATE usa_customers
SET email = '[email protected]'
WHERE name = 'John Doe';

-- Delete through view
DELETE FROM usa_customers
WHERE name = 'Bob Wilson';

Note:

Views are updatable if they:
- Select from a single table
- Don't use DISTINCT, GROUP BY, HAVING
- Don't use aggregate functions
- Don't use UNION, INTERSECT, EXCEPT

🔹 Materialized Views

Materialized views physically store query results, unlike regular views. They improve performance for expensive queries but require manual refreshing to update the stored data when underlying tables change.

-- Create materialized view
CREATE MATERIALIZED VIEW monthly_sales AS
SELECT 
    DATE_TRUNC('month', order_date) AS month,
    COUNT(*) AS order_count,
    SUM(amount) AS total_sales
FROM orders
GROUP BY DATE_TRUNC('month', order_date);

-- Query materialized view (fast!)
SELECT * FROM monthly_sales;

-- Refresh materialized view
REFRESH MATERIALIZED VIEW monthly_sales;

-- Refresh without locking (concurrent)
REFRESH MATERIALIZED VIEW CONCURRENTLY monthly_sales;

Result:

month       | order_count | total_sales
------------+-------------+-------------
2024-01-01  | 2           | 450.00
2024-02-01  | 1           | 200.00

🔹 Managing Views

PostgreSQL provides commands to modify, replace, and remove views. You can also query system catalogs to see all views and their definitions in your database.

-- Replace existing view
CREATE OR REPLACE VIEW customer_orders AS
SELECT 
    c.name,
    c.country,
    o.amount,
    o.order_date
FROM customers c
JOIN orders o ON c.id = o.customer_id;

-- Rename view
ALTER VIEW customer_orders RENAME TO order_details;

-- Drop view
DROP VIEW IF EXISTS order_details;

-- Drop materialized view
DROP MATERIALIZED VIEW IF EXISTS monthly_sales;

-- View all views in database
SELECT table_name, view_definition
FROM information_schema.views
WHERE table_schema = 'public';

🔹 View Benefits

Views provide multiple advantages for database design and application development. They help organize complex queries, improve security, and maintain consistent data access patterns across your applications.

  • Simplicity: Hide complex JOINs and calculations
  • Security: Restrict access to specific columns
  • Consistency: Ensure same query logic everywhere
  • Abstraction: Change underlying tables without affecting queries
  • Performance: Materialized views cache expensive queries
  • Organization: Logical grouping of related data

🧠 Test Your Knowledge

What type of view stores data physically?