SQL Tutorial › Performance & Objects › Views

SQL Views

IntermediateLesson 62 of 6911 min read6 queries run on MySQL 8.4

A view is a saved SELECT with a name. You query it like a table, but it stores no data of its own: every time you read it, MySQL runs the underlying query on the current data. Views hide complex joins behind a simple name, give every report the same definition of “revenue”, and let you expose only some columns to some users.

Advertisement
In this lesson
  • Create and query a view
  • Change and drop views
  • Know when a view is updatable and what WITH CHECK OPTION does
  • Use views for simplicity and security

CREATE VIEW

An order summary that every report can reuse:

SQL
CREATE VIEW order_summary ASSELECT o.order_id, o.order_date, o.status, c.customer_name,       SUM(oi.quantity * p.price) AS order_totalFROM orders oJOIN customers c    ON c.customer_id = o.customer_idJOIN order_items oi ON oi.order_id = o.order_idJOIN products p     ON p.product_id = oi.product_idGROUP BY o.order_id, o.order_date, o.status, c.customer_name; SELECT * FROM order_summary WHERE status = 'Delivered' ORDER BY order_total DESC;
ResultMySQL 8.4
mysql> CREATE VIEW order_summary AS
Query OK, 0 rows affected
mysql> SELECT * FROM order_summary WHERE status = 'Delivered' ORDER BY order_…
order_idorder_datestatuscustomer_nameorder_total
10022025-01-17DeliveredRohit Kumar8999
10012025-01-05DeliveredAnanya Sharma4744
10032025-02-02DeliveredAnanya Sharma4298
10092025-05-15DeliveredFatima Khan3499
10052025-03-08DeliveredDavid Fernandes3286
10102025-06-01DeliveredIshita Bose1145
10072025-04-10DeliveredRohit Kumar799
7 rows in set
How this query works, step by step
  1. CREATE VIEW order_summary AS SELECT ... saves the query under a name. No rows are copied.
  2. SELECT * FROM order_summary WHERE ... reads it like a table.
  3. MySQL combines the view’s query with your WHERE and ORDER BY and runs them on the live tables.
Advertisement

A view always shows current data

SQL
CREATE VIEW low_stock ASSELECT product_id, product_name, stock FROM products WHERE stock < 20;SELECT * FROM low_stock;UPDATE products SET stock = 5 WHERE product_id = 2;SELECT * FROM low_stock;
ResultMySQL 8.4
mysql> CREATE VIEW low_stock AS
Query OK, 0 rows affected
mysql> SELECT * FROM low_stock
product_idproduct_namestock
3USB-C Hub0
4Office Chair12
5Standing Desk5
9Monitor Arm18
4 rows in set
mysql> UPDATE products SET stock = 5 WHERE product_id = 2
Query OK, 1 row affected
mysql> SELECT * FROM low_stock
product_idproduct_namestock
2Mechanical Keyboard5
3USB-C Hub0
4Office Chair12
5Standing Desk5
9Monitor Arm18
5 rows in set
How this query works, step by step
  1. The first read lists the products with fewer than 20 in stock.
  2. After the keyboard’s stock drops to 5, the same view includes it, without any change to the view.

Change and drop a view

MySQL
CREATE VIEW low_stock AS SELECT product_id, product_name, stock FROM products WHERE stock < 20;CREATE OR REPLACE VIEW low_stock ASSELECT product_id, product_name, category, stock FROM products WHERE stock < 10;SELECT * FROM low_stock;DROP VIEW low_stock;
ResultMySQL 8.4
mysql> CREATE VIEW low_stock AS SELECT product_id, product_name, stock FROM p…
Query OK, 0 rows affected
mysql> CREATE OR REPLACE VIEW low_stock AS
Query OK, 0 rows affected
mysql> SELECT * FROM low_stock
product_idproduct_namecategorystock
3USB-C HubElectronics0
5Standing DeskFurniture5
2 rows in set
mysql> DROP VIEW low_stock
Query OK, 0 rows affected

SHOW FULL TABLES WHERE Table_type = 'VIEW'; lists the views in a database, and SHOW CREATE VIEW name; shows a view’s query.

Advertisement

Updatable views

A simple view over one table, without GROUP BY, DISTINCT, aggregates or UNION, is updatable: changes go straight to the base table.

MySQL
CREATE VIEW furniture ASSELECT product_id, product_name, price, stock FROM products WHERE category = 'Furniture';UPDATE furniture SET price = price - 500 WHERE product_id = 4;SELECT product_id, product_name, price FROM products WHERE product_id = 4;
ResultMySQL 8.4
mysql> CREATE VIEW furniture AS
Query OK, 0 rows affected
mysql> UPDATE furniture SET price = price – 500 WHERE product_id = 4
Query OK, 1 row affected
mysql> SELECT product_id, product_name, price FROM products WHERE product_id …
product_idproduct_nameprice
4Office Chair8499
1 row in set

A view with an aggregate is not:

MySQL
CREATE VIEW category_stock AS SELECT category, SUM(stock) AS units FROM products GROUP BY category;UPDATE category_stock SET units = 0 WHERE category = 'Furniture';
ResultMySQL 8.4
mysql> CREATE VIEW category_stock AS SELECT category, SUM(stock) AS units FRO…
Query OK, 0 rows affected
mysql> UPDATE category_stock SET units = 0 WHERE category = 'Furniture'
ERROR 1288 (HY000): The target table category_stock of the UPDATE is not updatable
Advertisement

WITH CHECK OPTION

Without it, you can insert rows through a view that the view itself will not show. WITH CHECK OPTION refuses them:

MySQL
CREATE VIEW furniture ASSELECT product_id, product_name, category, price, stock FROM products WHERE category = 'Furniture'WITH CHECK OPTION;INSERT INTO furniture VALUES (20, 'Bookshelf', 'Furniture', 4999, 8);INSERT INTO furniture VALUES (21, 'Stapler', 'Stationery', 299, 40);
ResultMySQL 8.4
mysql> CREATE VIEW furniture AS
Query OK, 0 rows affected
mysql> INSERT INTO furniture VALUES (20, 'Bookshelf', 'Furniture', 4999, 8)
Query OK, 1 row affected
mysql> INSERT INTO furniture VALUES (21, 'Stapler', 'Stationery', 299, 40)
ERROR 1369 (HY000): CHECK OPTION failed 'company.furniture'
How this query works, step by step
  1. The bookshelf is Furniture, matches the view’s WHERE, and is inserted.
  2. The stapler is Stationery, which the view would not show, so WITH CHECK OPTION rejects it.

Views for security

Give an analyst access to staff names and departments but not salaries:

MySQL
CREATE VIEW staff_directory ASSELECT emp_id, first_name, last_name, dept_id, city FROM employees; GRANT SELECT ON company.staff_directory TO 'analyst'@'localhost';

The analyst can query staff_directory but has no privilege on employees itself. See GRANT.

View vs table

TableView
Stores datayesno (only the query)
Always currentyesyes, computed on every read
Can have its own indexesyesno, it uses the base tables’ indexes
Speeddirectsame as running the query

MySQL has no materialized views. To store a precomputed result, write it into a summary table (for example with CREATE TABLE ... AS SELECT) and refresh it on a schedule.

Quick quiz

1. Does a view store a copy of the data?

2. Which view can be updated?

3. What does WITH CHECK OPTION prevent?

Advertisement

Views FAQ

What is a view in SQL?

A virtual table defined by a SELECT query. It has a name and columns like a table but stores no data; its rows are computed when it is queried.

What is the difference between a view and a table?

A table stores data. A view stores a query and shows the current result of that query each time you read it.

Can we insert data into a view?

Yes, if the view is updatable: based on one table, with no aggregates, GROUP BY, DISTINCT or UNION. The rows go into the base table.

Does MySQL support materialized views?

No. Use a summary table refreshed by a scheduled event or batch job instead.