Skip to content

Views and Virtual Tables

Difficulty: Intermediate
Generated on: 2025-07-10 02:27:29
Category: SQL Cheatsheet for Database Development


SQL Cheatsheet: Views and Virtual Tables (Intermediate Level)

Section titled “SQL Cheatsheet: Views and Virtual Tables (Intermediate Level)”

What are Views?

Views are virtual tables based on the result-set of a SQL statement. They don’t store data themselves; instead, they store the query definition. When you query a view, the underlying query is executed, and the results are presented as if they were a table.

When to Use Views:

  • Simplifying Complex Queries: Break down complex joins, aggregations, and subqueries into manageable, reusable units.
  • Data Abstraction: Hide underlying table structures and sensitive data from users. Provide a simplified, tailored view of the data.
  • Data Security: Grant users access only to specific columns or rows of data.
  • Data Consistency: Ensure consistent data presentation across multiple applications or reports.
  • Report Generation: Create pre-defined datasets for reporting tools.
-- Creating a View
CREATE [OR REPLACE] VIEW view_name AS
SELECT column1, column2, ...
FROM table_name
WHERE condition;
-- Example
CREATE VIEW customer_summary AS
SELECT customer_id, first_name, last_name, email
FROM customers
WHERE country = 'USA';
-- Querying a View
SELECT * FROM view_name;
-- Example
SELECT * FROM customer_summary;
-- Dropping a View
DROP VIEW view_name;
-- Example
DROP VIEW customer_summary;
-- Updatable Views (Restrictions Apply)
-- Generally, views are updatable if they meet certain criteria:
-- - The view is based on a single table.
-- - The view does not contain aggregate functions (e.g., SUM, AVG, COUNT).
-- - The view does not contain DISTINCT.
-- - The view does not contain GROUP BY or HAVING clauses.
-- - The view does not use UNION, INTERSECT, or EXCEPT.
UPDATE view_name
SET column1 = value1, column2 = value2
WHERE condition;
-- Example (if customer_summary was based on a single table and met the criteria)
UPDATE customer_summary
SET email = 'new_email@example.com'
WHERE customer_id = 123;
  • Creating a sales_summary view to show total sales per product:

    CREATE VIEW sales_summary AS
    SELECT
    product_name,
    SUM(quantity * price) AS total_sales
    FROM
    orders
    JOIN
    order_items ON orders.order_id = order_items.order_id
    JOIN
    products ON order_items.product_id = products.product_id
    GROUP BY
    product_name;
    SELECT * FROM sales_summary ORDER BY total_sales DESC;
  • Creating a customer_orders view to show orders for a specific customer:

    CREATE VIEW customer_orders AS
    SELECT
    order_id,
    order_date,
    total_amount
    FROM
    orders
    WHERE
    customer_id = 1; -- Replace 1 with a specific customer ID
    SELECT * FROM customer_orders;
  • Creating a employee_salary_info view masking salary details except for department heads:

    CREATE VIEW employee_salary_info AS
    SELECT
    employee_id,
    first_name,
    last_name,
    department,
    CASE
    WHEN is_department_head = 1 THEN salary -- Only show salary for department heads
    ELSE NULL
    END AS salary
    FROM
    employees;
    SELECT * FROM employee_salary_info;
  • Creating a view that calculates the average order value:

    CREATE VIEW avg_order_value AS
    SELECT AVG(total_amount) AS average_order_value
    FROM orders;
    SELECT * FROM avg_order_value;
  • Use Descriptive Names: Choose view names that clearly indicate their purpose.

  • Keep Views Simple: Avoid overly complex views. Break down complex logic into multiple, smaller views if necessary. This aids in maintainability and debugging.

  • Consider Materialized Views (if available): For performance-critical scenarios, explore materialized views. These views store the result set physically, improving query performance at the cost of storage space and requiring periodic refresh. Not all databases support materialized views.

  • Optimize the Underlying Queries: Ensure the queries used to define the views are optimized for performance. Use indexes appropriately on the base tables.

  • Avoid SELECT *: Specify the columns you need in the SELECT statement to reduce the amount of data retrieved and improve performance. This is especially important when the underlying tables are large.

  • Use WITH CHECK OPTION (for Updatable Views): When creating updatable views, use the WITH CHECK OPTION clause to ensure that any data modifications through the view satisfy the view’s WHERE clause. This prevents invalid data from being inserted through the view.

    CREATE VIEW updatable_view AS
    SELECT column1, column2
    FROM table1
    WHERE column1 > 10
    WITH CHECK OPTION;
    -- Example: Attempting to insert a row that violates the view's WHERE clause
    -- This will fail because column1 is not > 10
    INSERT INTO updatable_view (column1, column2) VALUES (5, 'value');
  • Understand View Dependencies: Be aware of the dependencies between views and tables. Dropping or modifying a table can affect views that depend on it. Some databases provide tools to track dependencies.

Sample Data:

-- Customers Table
CREATE TABLE Customers (
customer_id INT PRIMARY KEY,
first_name VARCHAR(50),
last_name VARCHAR(50),
email VARCHAR(100),
country VARCHAR(50)
);
INSERT INTO Customers (customer_id, first_name, last_name, email, country) VALUES
(1, 'John', 'Doe', 'john.doe@example.com', 'USA'),
(2, 'Jane', 'Smith', 'jane.smith@example.com', 'Canada'),
(3, 'Peter', 'Jones', 'peter.jones@example.com', 'UK'),
(4, 'Maria', 'Garcia', 'maria.garcia@example.com', 'Spain');
-- Orders Table
CREATE TABLE Orders (
order_id INT PRIMARY KEY,
customer_id INT,
order_date DATE,
total_amount DECIMAL(10, 2),
FOREIGN KEY (customer_id) REFERENCES Customers(customer_id)
);
INSERT INTO Orders (order_id, customer_id, order_date, total_amount) VALUES
(101, 1, '2023-01-15', 150.00),
(102, 2, '2023-02-20', 200.00),
(103, 1, '2023-03-10', 75.00),
(104, 3, '2023-04-05', 300.00);

Example 1: Customers from a Specific Country

CREATE VIEW usa_customers AS
SELECT customer_id, first_name, last_name, email
FROM Customers
WHERE country = 'USA';
SELECT * FROM usa_customers;
-- Output:
-- customer_id | first_name | last_name | email
-- ----------- | ---------- | --------- | ---------------------
-- 1 | John | Doe | john.doe@example.com

Example 2: Customer Order Summary

CREATE VIEW customer_order_summary AS
SELECT
c.customer_id,
c.first_name,
c.last_name,
COUNT(o.order_id) AS total_orders,
SUM(o.total_amount) AS total_spent
FROM
Customers c
LEFT JOIN
Orders o ON c.customer_id = o.customer_id
GROUP BY
c.customer_id, c.first_name, c.last_name;
SELECT * FROM customer_order_summary;
-- Output:
-- customer_id | first_name | last_name | total_orders | total_spent
-- ----------- | ---------- | --------- | ------------ | -----------
-- 1 | John | Doe | 2 | 225.00
-- 2 | Jane | Smith | 1 | 200.00
-- 3 | Peter | Jones | 1 | 300.00
-- 4 | Maria | Garcia | 0 | 0.00

Example 3: High-Value Orders (Orders exceeding a certain amount)

CREATE VIEW high_value_orders AS
SELECT order_id, customer_id, order_date, total_amount
FROM Orders
WHERE total_amount > 200;
SELECT * FROM high_value_orders;
-- Output:
-- order_id | customer_id | order_date | total_amount
-- -------- | ----------- | ---------- | ------------
-- 104 | 3 | 2023-04-05 | 300.00
  • Performance Issues: Poorly designed views can lead to performance bottlenecks. Analyze query execution plans and optimize the underlying queries. Avoid excessive use of complex joins and subqueries in views.

  • Updatability Issues: Not all views are updatable. Understand the restrictions on updatable views and design views accordingly if you need to modify data through them. Using INSTEAD OF triggers can sometimes work around this limitation, but increase complexity.

  • Circular Dependencies: Avoid creating views that depend on each other in a circular fashion (e.g., view A depends on view B, and view B depends on view A). This can lead to errors and make it difficult to maintain the views.

  • Data Masking Errors: When using views for data masking or security, carefully design the view’s WHERE clause and column selection to ensure that sensitive data is properly protected. Regularly review and test your data masking views.

  • Unexpected Results After Schema Changes: Modifications to the underlying tables (e.g., adding, dropping, or renaming columns) can break views. Implement a robust change management process to ensure that views are updated accordingly after schema changes.

  • Incorrectly Using WITH CHECK OPTION: If you use WITH CHECK OPTION and the underlying data is changed directly (not through the view), it can cause inconsistencies. Use this option with caution.

Troubleshooting:

  • View does not exist: Double-check the view name and schema.
  • Invalid object name: The view depends on a table or column that no longer exists.
  • Incorrect syntax: Review the view definition for syntax errors.
  • Performance is slow: Analyze the query execution plan and optimize the underlying query. Consider materialized views if appropriate.
  • Cannot update view: Review the restrictions on updatable views. Consider using INSTEAD OF triggers.
  • MySQL: Supports standard view creation and querying. Materialized views are not supported natively. You can simulate materialized views with scheduled tasks that update a table with the view’s results.
  • PostgreSQL: Supports standard views and also materialized views. Materialized views can be refreshed manually or automatically.
  • SQL Server: Supports standard views. Also supports indexed views, which are similar to materialized views in that they store the result set and can be indexed. Requires certain configuration settings.
  • Oracle: Supports standard views, materialized views, and read-only materialized views. Offers various refresh options for materialized views (e.g., COMPLETE, FAST, ON DEMAND, ON COMMIT).

Key Differences Table:

FeatureMySQLPostgreSQLSQL ServerOracle
Standard ViewsYesYesYesYes
Materialized ViewsSimulatedYesIndexed ViewsYes
Refresh OptionsN/AManual/AutoManualFlexible

This cheatsheet provides a solid foundation for working with views and virtual tables in SQL. Remember to adapt the examples and best practices to your specific database system and application requirements. Always prioritize performance, security, and maintainability when designing and implementing views.