MySQL Create View
A view is a named, saved SELECT query that you can use like a table. It stores no data of its own. Every time you query it, MySQL runs the saved query against the current data. Views simplify complex queries, hide sensitive columns and give applications a stable interface even when tables change.
1. What is a View?
SELECT. Each time you query it, MySQL reads the latest data from the base tables.- Simplify: wrap a long join or calculation in a short name.
- Secure: expose only some columns or rows to a user.
- Stable interface: rename or split tables later while keeping the view's shape.
- Always current: results reflect the base tables at query time.
2. Syntax
CREATE [OR REPLACE]
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[SQL SECURITY {DEFINER | INVOKER}]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION];
3. A Simple View
CREATE VIEW emp_directory AS
SELECT e.name, d.dept_name
FROM employees e
JOIN departments d ON d.dept_id = e.dept_id
WHERE e.active = TRUE;
SELECT * FROM emp_directory ORDER BY name;
Result: 4 rows
| name | dept_name |
|---|---|
| Usha | Sales |
| Varun | Support |
| Wasim | Sales |
| Yamini | Research |
You can filter, sort and join a view just like a table:
SELECT name FROM emp_directory WHERE dept_name = 'Sales';
Result: 2 rows
| name |
|---|
| Usha |
| Wasim |
4. Views Always Show Current Data
INSERT INTO employees VALUES (6, 'Aditi', 'aditi@corp.example', 58000, 30, TRUE);
SELECT * FROM emp_directory WHERE dept_name = 'Research';
Result: 2 rows
| name | dept_name |
|---|---|
| Yamini | Research |
| Aditi | Research |
No refresh was needed: the view re-ran its query.
5. Views with Calculations and Column Names
Give view columns clear names with aliases or a column list:
CREATE VIEW dept_payroll (department, headcount, total_salary, avg_salary) AS
SELECT d.dept_name, COUNT(e.emp_id), SUM(e.salary), ROUND(AVG(e.salary), 0)
FROM departments d
LEFT JOIN employees e ON e.dept_id = d.dept_id AND e.active = TRUE
GROUP BY d.dept_name;
SELECT * FROM dept_payroll ORDER BY total_salary DESC;
Result: 3 rows
| department | headcount | total_salary | avg_salary |
|---|---|---|---|
| Research | 2 | 148000.00 | 74000 |
| Sales | 2 | 129000.00 | 64500 |
| Support | 1 | 52000.00 | 52000 |
6. CREATE OR REPLACE and ALTER VIEW
Creating a view that already exists fails; CREATE OR REPLACE redefines it:
CREATE VIEW emp_directory AS SELECT name FROM employees;
ERROR 1050 (42S01): Table 'emp_directory' already exists
CREATE OR REPLACE VIEW emp_directory AS
SELECT e.name, e.email, d.dept_name
FROM employees e JOIN departments d ON d.dept_id = e.dept_id
WHERE e.active = TRUE;
SELECT * FROM emp_directory WHERE dept_name = 'Support';
Result: 1 row
| name | dept_name | |
|---|---|---|
| Varun | varun@corp.example | Support |
ALTER VIEW view_name AS select… does the same for an existing view, but fails if the view doesn't exist.
7. Updatable Views
A simple view (one table, no GROUP BY, DISTINCT, aggregates, UNION or sub-queries in the select list) can be used in UPDATE, INSERT and DELETE; the change goes to the base table:
CREATE VIEW support_staff AS
SELECT emp_id, name, salary, dept_id FROM employees WHERE dept_id = 20;
UPDATE support_staff SET salary = salary + 3000 WHERE name = 'Varun';
SELECT emp_id, name, salary FROM employees WHERE emp_id = 2;
Result: 1 row
| emp_id | name | salary |
|---|---|---|
| 2 | Varun | 55000.00 |
Aggregate views can't be updated:
UPDATE dept_payroll SET headcount = 10 WHERE department = 'Sales';
ERROR 1288 (HY000): The target table dept_payroll of the UPDATE is not updatable
8. WITH CHECK OPTION
Through support_staff you could insert someone into Sales, and the row would vanish from the view. WITH CHECK OPTION stops changes that don't satisfy the view's WHERE:
CREATE OR REPLACE VIEW support_staff AS
SELECT emp_id, name, salary, dept_id FROM employees WHERE dept_id = 20
WITH CHECK OPTION;
INSERT INTO support_staff VALUES (7, 'Bhoomi', 50000, 20); -- allowed
INSERT INTO support_staff VALUES (8, 'Chirag', 50000, 10); -- Sales: rejected
Query OK, 0 rows affected
Query OK, 1 row affected
ERROR 1369 (HY000): CHECK OPTION failed 'company.support_staff'
9. Using Views for Security
Give a user access to the view only, not the table, so salaries stay private:
CREATE USER 'reception'@'localhost' IDENTIFIED BY 'Front#Desk26';
GRANT SELECT ON company.emp_directory TO 'reception'@'localhost';
SELECT name, dept_name FROM emp_directory ORDER BY name LIMIT 3;
Result: 3 rows
| name | dept_name |
|---|---|
| Aditi | Research |
| Bhoomi | Support |
| Usha | Sales |
SELECT name, salary FROM employees;
ERROR 1142 (42000): SELECT command denied to user 'reception'@'localhost' for table 'employees'
SQL SECURITY DEFINER), which is why reception can read through it without rights on the tables. SQL SECURITY INVOKER checks the caller's privileges instead.10. How MySQL Processes a View
| ALGORITHM | How it works | Notes |
|---|---|---|
| MERGE | The view's SQL is merged into your query | Fast; indexes on base tables are used; required for updatable views |
| TEMPTABLE | The view result is materialised into a temporary table first | Needed for GROUP BY, DISTINCT, UNION; not updatable |
| UNDEFINED (default) | MySQL picks MERGE when possible | Usually leave this |
11. Inspecting Views
SHOW FULL TABLES WHERE Table_type = 'VIEW';
Result: 3 rows
| Tables_in_company | Table_type |
|---|---|
| dept_payroll | VIEW |
| emp_directory | VIEW |
| support_staff | VIEW |
SELECT table_name, is_updatable, check_option, security_type
FROM information_schema.views
WHERE table_schema = 'company';
Result: 3 rows
| TABLE_NAME | IS_UPDATABLE | CHECK_OPTION | SECURITY_TYPE |
|---|---|---|---|
| dept_payroll | NO | NONE | DEFINER |
| emp_directory | YES | NONE | DEFINER |
| support_staff | YES | CASCADED | DEFINER |
12. Practice Exercises
Exercise 1: Create a view high_earners showing name and salary of active employees earning more than 60,000.
CREATE VIEW high_earners AS
SELECT name, salary FROM employees WHERE active = TRUE AND salary > 60000;
SELECT * FROM high_earners ORDER BY salary DESC;
Result: 3 rows
| name | salary |
|---|---|
| Yamini | 90000.00 |
| Usha | 68000.00 |
| Wasim | 61000.00 |
Exercise 2: Create a view listing each department with the name of its highest-paid employee.
CREATE VIEW dept_top_earner AS
SELECT d.dept_name, e.name, e.salary
FROM employees e JOIN departments d ON d.dept_id = e.dept_id
WHERE e.salary = (SELECT MAX(salary) FROM employees WHERE dept_id = e.dept_id);
SELECT * FROM dept_top_earner ORDER BY dept_name;
Result: 3 rows
| dept_name | name | salary |
|---|---|---|
| Research | Yamini | 90000.00 |
| Sales | Usha | 68000.00 |
| Support | Varun | 55000.00 |
13. Summary
CREATE VIEW name AS SELECT …;saves a query you can use like a table.- Views store no data; they always show the current data of the base tables.
CREATE OR REPLACE VIEWredefines a view;ALTER VIEWchanges an existing one.- Simple single-table views are updatable;
WITH CHECK OPTIONkeeps changes inside the view's filter. - Grant access to views instead of tables to hide sensitive columns.