Articles

What Is a Database View?

A database view is a saved SQL query that behaves like a table — simplifying complex joins and restricting access, without storing the data twice.

The Lycoris Team The Lycoris Team · · 4 min read
Abstract illustration of database tables

A database view is a stored SQL query that you can query as if it were a table. It doesn’t hold its own copy of the data — every time you SELECT from a view, the database re-runs the underlying query against the real tables and returns the result. Views exist to hide complexity, standardize a definition of “the data” across an application, and restrict what a given user can see, all without duplicating storage.

Creating and using a view

CREATE VIEW active_customers AS
SELECT c.id, c.name, c.email, COUNT(o.id) AS order_count
FROM customers c
JOIN orders o ON o.customer_id = c.id
WHERE c.status = 'active'
GROUP BY c.id, c.name, c.email;

From this point on, anyone can query active_customers like a normal table:

SELECT * FROM active_customers WHERE order_count > 5;

The database expands this into the full join-and-group-by query underneath, every single time. There’s no separate storage for active_customers — it’s a name attached to a query definition, kept in the database’s system catalog.

Why use a view instead of just writing the query

The main reason is to hide a query’s complexity behind a stable name. If five different parts of an application need “active customers with their order counts,” writing that join five separate times means five places to update when the definition of “active” changes. A view centralizes that definition: change the CREATE VIEW statement once, and every query against active_customers picks up the new logic automatically.

Views are also a natural access-control boundary. If a table has sensitive columns — salary, social security numbers, internal notes — you can grant a role access to a view that excludes those columns, rather than the underlying table:

CREATE VIEW employee_directory AS
SELECT id, name, department, office_location
FROM employees;

GRANT SELECT ON employee_directory TO reporting_role;

reporting_role can query names and departments but has no path to the salary column, even though it lives in the same underlying employees table.

Views vs materialized views

A plain view is always live — it reflects the current state of the underlying tables the instant you query it, because it re-executes the query on every access. That’s also its cost: a view built on a complex join across large tables is exactly as slow as running that join directly, every time, because that’s literally what happens.

A materialized view solves the performance problem by actually storing the result set and refreshing it on a schedule or on demand, trading freshness for speed. For a full breakdown of when to reach for each, see views vs materialized views.

Plain viewMaterialized view
Stores dataNo — re-runs the queryYes — stores the result set
Always currentYesNo — until next refresh
Query speedSame as the underlying queryFast — reads stored data
Write overheadNoneRefresh cost, on a schedule or trigger

Updatable views

Some views can be written to, not just read from — an UPDATE, INSERT, or DELETE against the view is translated into the equivalent operation on the underlying table. This only works for simple views: a single-table view with no aggregation, no GROUP BY, and no DISTINCT is usually updatable; a view built on a multi-table join or an aggregate function generally isn’t, because the database can’t unambiguously map a change in the view back to a specific row in a specific source table.

CREATE VIEW active_employees AS
SELECT id, name, department
FROM employees
WHERE terminated_at IS NULL;

UPDATE active_employees SET department = 'Engineering' WHERE id = 42;

That UPDATE is rewritten against the employees table directly. Most database engines let you inspect whether a specific view is updatable, and some support INSTEAD OF triggers to define custom logic for what an insert or update against a non-trivial view should actually do.

Views and query optimization

A view doesn’t change what the database’s query optimizer does — it sees straight through the view definition to the underlying tables and plans the query the same way it would if you’d written the join yourself. This is worth knowing because it means wrapping a slow query in a view doesn’t make it faster; it just gives the same slow query a name. Indexing strategy, join order, and the shape of the underlying tables still determine performance, the same as if the view didn’t exist.

When views cause problems

Layering views on top of other views is common in large codebases and can quietly hurt performance — a view built on a view built on a view still has to be flattened into one query plan at execution time, and a few levels of nesting can make that plan much harder for the optimizer to reason about well. It also makes the actual query being run much harder for a human to reconstruct when debugging a slow report. As a rule of thumb, keep view nesting shallow, and if a view has become the backbone of a frequently-run, expensive report, that’s usually a sign to migrate it to a materialized view or a proper ETL pipeline instead.

The takeaway

A database view is a named, reusable SQL query — not a copy of data, but a lens onto the tables it queries, recomputed every time it’s read. Use views to simplify recurring complex queries, enforce a single definition of a business concept across an application, and restrict column-level or row-level access without duplicating tables. When a view’s query is too expensive to re-run on every access, that’s the signal to reach for a materialized view instead, trading some data freshness for real stored results.

The Lycoris Team The Lycoris Team · · 4 min read

Index Cardinality: Why Some Indexes Don't Help

Cardinality is how many distinct values a column has. Low-cardinality columns make poor index candidates because the database still scans most of the table.

#Databases #SQL #Computer Science
The Lycoris Team The Lycoris Team · · 5 min read

Clustered vs Non-Clustered Index Explained

A clustered index determines the physical row order on disk; a non-clustered index is a separate lookup structure. How they differ and when to use each.

#Databases #SQL #Performance