Getting Started With Database Views in SQL: A Beginner's Guide
Learn SQL database views from scratch: what they are, how to create them, when to use them, and how indexed views speed up queries. Simple and beginner-friendly.
Imagine your mother keeps one big steel trunk at home. Inside it she stores everything: clothes, documents, school certificates, old photos, and bills. Finding your birth certificate means digging through the whole trunk every single time. Tiring, right?
Now imagine she makes a small labelled folder called "School Papers" that points only to your certificates. She did not make a second copy of every document. The folder just shows the right papers when she opens it. The originals still live in the trunk.
A database view works exactly like that labelled folder. It is a saved window that shows you only the rows and columns you care about, pulled from your big tables. You did not copy the data. You just made an easy, clean way to look at it.
In this guide you will learn what views are, why they are useful, how to create them, and a few smart tricks like indexed views. We will keep it simple and friendly. Let us begin.
What exactly is a view?
A view is a virtual table. It looks and behaves like a table, but it does not normally store any data itself. Instead, it stores a SQL query. When you ask the view for data, the database runs that saved query and shows you the result.
Think of it as giving a nickname to a long, complicated question. Once you save the question as a view, you can ask it again just by calling its name.
Here is the key idea, said simply: a table holds the data, a view holds the question.
Why do people use views?
Views are popular because they solve real everyday problems. Let us look at the main reasons.
| Reason | What it means in plain words |
|---|---|
| Simplicity | Hide a long, scary join behind one short name. |
| Security | Show some columns, hide secret ones like salary or password. |
| Consistency | Everyone uses the same correct query, so reports match. |
| Reusability | Write the logic once, use it in many places. |
| Cleaner code | Your application reads SELECT * FROM ActiveCustomers instead of 20 lines of SQL. |
A very common case is security. Suppose your Employees table has a Salary column. You do not want the front-desk staff to see salaries. You can build a view that shows name, department, and phone number only, and then give the staff access to the view instead of the table. They see what they need, and the salary stays private.
How a view protects sensitive data
Steps
Employees table
Has name, dept, salary
SafeStaffView
Shows name and dept only
Front-desk user
Reads view, no salary
Setting up some sample tables
Before we make a view, we need some tables to look at. Let us create two small tables: Customers and Orders. We will use Transact-SQL (T-SQL), which is the SQL language used by Microsoft SQL Server.
CREATE TABLE Customers (
CustomerId INT PRIMARY KEY,
FullName NVARCHAR(100),
City NVARCHAR(50),
IsActive BIT
);
CREATE TABLE Orders (
OrderId INT PRIMARY KEY,
CustomerId INT,
Amount DECIMAL(10, 2),
OrderDate DATE
);Now imagine these tables have thousands of rows. Some customers are active, some are not. We often want to work with only the active ones. Writing WHERE IsActive = 1 again and again gets boring and error-prone. This is the perfect job for a view.
Creating your first view
To create a view, you use the CREATE VIEW statement, give it a name, and then write the query after the word AS.
CREATE VIEW ActiveCustomers
AS
SELECT
CustomerId,
FullName,
City
FROM Customers
WHERE IsActive = 1;That is it. You have made a view called ActiveCustomers. Now you can use it just like a table:
SELECT * FROM ActiveCustomers
WHERE City = 'Mumbai';When you run this, SQL Server quietly runs the saved query, applies your extra WHERE City = 'Mumbai' filter on top, and hands back the matching rows. You never see the IsActive = 1 part again. It is hidden inside the view.
Views that join many tables
The real magic shows up when your data lives in more than one table. Suppose your boss wants a report showing each customer's name next to how much they spent. That needs a join between Customers and Orders. Joins can be hard for beginners. So we hide the join inside a view once, and everyone reuses it.
CREATE VIEW CustomerSpending
AS
SELECT
c.FullName,
c.City,
SUM(o.Amount) AS TotalSpent
FROM Customers AS c
INNER JOIN Orders AS o
ON c.CustomerId = o.CustomerId
GROUP BY c.FullName, c.City;Now anyone on your team can simply run:
SELECT * FROM CustomerSpending
ORDER BY TotalSpent DESC;They get a clean spending report without ever writing a join. They do not even need to know the tables are connected. The view did the hard work for them. This is what makes views so loved in teams.
One join, many readers
Steps
Write join once
Hard SQL, done by you
Save as view
CustomerSpending
Team reuses it
Simple SELECT only
Changing and removing a view
Views are not set in stone. You will often want to tweak the query later. You have two clean ways to do that.
The first is ALTER VIEW. It keeps the same view name but replaces the query inside it.
ALTER VIEW ActiveCustomers
AS
SELECT
CustomerId,
FullName,
City,
IsActive
FROM Customers
WHERE IsActive = 1;If you no longer need a view, you remove it with DROP VIEW. Removing a view never harms your real tables, because the view held no data. Only the saved question goes away.
DROP VIEW CustomerSpending;Here is a quick map of the common commands so you can remember them at a glance.
| Command | What it does |
|---|---|
CREATE VIEW | Make a brand new view. |
ALTER VIEW | Change the query inside an existing view. |
DROP VIEW | Delete the view. Tables are safe. |
SELECT FROM view | Read data through the view. |
Can I update data through a view?
This is a question almost every beginner asks. The short answer is: sometimes yes, sometimes no.
If your view is simple, meaning it reads from one table and does not use GROUP BY, DISTINCT, or aggregate functions like SUM, then you can usually run INSERT, UPDATE, and DELETE through it. SQL Server passes the change down to the real table.
UPDATE ActiveCustomers
SET City = 'Delhi'
WHERE CustomerId = 5;But if your view uses a join or a GROUP BY (like our CustomerSpending view), it is usually read-only. SQL Server cannot guess which table a change belongs to. To allow writes on a complex view, advanced users add an INSTEAD OF trigger, but that is a topic for another day.
A faster kind: the indexed view
Normal views store no data. Every read runs the query again. For most cases that is perfectly fine. But what if your view does a heavy job, like summing millions of orders, and you read it hundreds of times a day? Running that big sum over and over is slow.
SQL Server has a clever answer called an indexed view (also called a materialized view in some databases). An indexed view actually stores its result on disk, like a real table. SQL Server keeps it updated automatically whenever the base tables change. So the heavy work is done once during writes, not every time you read.
To build one you need two steps. First, create the view with the WITH SCHEMABINDING option. This locks the view to the table structure so nobody accidentally breaks it. Then add a unique clustered index, which is what actually stores (materializes) the data.
CREATE VIEW dbo.OrderTotals
WITH SCHEMABINDING
AS
SELECT
CustomerId,
COUNT_BIG(*) AS OrderCount,
SUM(Amount) AS TotalAmount
FROM dbo.Orders
GROUP BY CustomerId;
CREATE UNIQUE CLUSTERED INDEX IX_OrderTotals
ON dbo.OrderTotals (CustomerId);After the index is created, the totals live on disk. Reading them is now very fast because SQL Server does not recompute the sum each time. It just reads the stored answer.
Here is a simple comparison to help you choose.
| Feature | Normal view | Indexed view |
|---|---|---|
| Stores data? | No | Yes, on disk |
| Read speed | Recomputes each time | Very fast, pre-computed |
| Write cost | None extra | Slightly slower writes |
| Needs SCHEMABINDING? | No | Yes |
| Best for | Most everyday cases | Heavy, repeated reports |
Two steps to build an indexed view
Steps
WITH SCHEMABINDING
Lock view to tables
CREATE UNIQUE CLUSTERED INDEX
Materialize the result
Data stored on disk
Fast reads
A word of caution. Indexed views are powerful but not free. Because the data is stored, every time the base tables change, SQL Server must update the stored view too. This makes inserts and updates a little slower. So use indexed views only when you read a heavy result far more often than you change the data. Do not turn every view into an indexed view.
Calling a view from C# and .NET
If you build apps with .NET, good news: a view behaves just like a table to your code. You can query it with plain ADO.NET, Dapper, or Entity Framework Core. Here is a tiny example using a SqlConnection to read our CustomerSpending view.
using Microsoft.Data.SqlClient;
const string connectionString =
"Server=localhost;Database=ShopDb;Trusted_Connection=True;Encrypt=False;";
await using var connection = new SqlConnection(connectionString);
await connection.OpenAsync();
const string sql = "SELECT FullName, TotalSpent FROM CustomerSpending ORDER BY TotalSpent DESC;";
await using var command = new SqlCommand(sql, connection);
await using var reader = await command.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
string name = reader.GetString(0);
decimal spent = reader.GetDecimal(1);
Console.WriteLine($"{name} spent {spent:C}");
}Notice that your C# code does not care that CustomerSpending is a view. It reads it the same way it would read a table. This is the beauty of views: they keep the messy SQL on the database side and give your app a clean, simple name to talk to. On modern setups this runs nicely on .NET 10, which is the current long-term support release.
Common beginner mistakes to avoid
A few gentle warnings so you do not stumble.
First, do not use SELECT * inside a view in serious projects. If someone later adds a column to the table, your view may behave in surprising ways. List the columns you want by name instead.
Second, remember that a normal view does not make slow queries fast by magic. If the underlying query is slow, the view will be slow too, because it runs the same query. Views organize and simplify; they do not speed things up unless you use an indexed view.
Third, avoid stacking too many views on top of each other (a view that reads a view that reads another view). It works, but it can become hard to debug and slow. Keep your view chains short and clear.
A quick mental model
If you remember just one picture, remember this. A table is a warehouse full of boxes. A view is a labelled window cut into the wall of that warehouse. Through the window you see only the boxes you wanted, arranged the way you wanted. You did not move or copy any box. You just made a nicer way to look in.
And an indexed view is like taking a photo through that window and pinning it to your desk, so you do not have to walk to the window every time. The photo updates itself whenever the boxes change.
References and further reading
- CREATE VIEW (Transact-SQL) - Microsoft Learn — the official syntax reference for creating views.
- Views - SQL Server - Microsoft Learn — a clear overview of what views are and how they are used.
- Create views - SQL Server - Microsoft Learn — step-by-step guide using SSMS and T-SQL.
- SQL Server Indexed View guide - SQL Server Tutorial — a friendly walk-through of indexed views with examples.
Quick recap
- A view is a saved query that looks like a table but normally stores no data of its own.
- Use views to simplify complex joins, protect sensitive columns, and reuse logic across a team.
- Create one with
CREATE VIEW name AS SELECT ..., change it withALTER VIEW, and remove it withDROP VIEW. - Simple single-table views can be written to; views with joins or
GROUP BYare usually read-only. - An indexed view (materialized view) stores its result on disk for fast reads, needs
WITH SCHEMABINDINGand a unique clustered index, but makes writes a little slower. - In .NET, a view is read just like a table using ADO.NET, Dapper, or EF Core.
- Avoid
SELECT *in views, remember views do not speed up slow queries by themselves, and keep view chains short.
Related Posts
A Complete Guide to Different Types of Joins in SQL
Learn SQL joins the easy way: INNER, LEFT, RIGHT, FULL OUTER, CROSS and SELF joins explained with simple tables, diagrams, and C# examples.
Calling Views, Stored Procedures and Functions in EF Core
A friendly, beginner guide to calling database views, stored procedures, and functions in EF Core with FromSql, SqlQuery, ExecuteSql, and ToView.
Get Started with SQL Transactions in PostgreSQL
Learn SQL transactions in PostgreSQL the easy way: BEGIN, COMMIT, ROLLBACK, ACID, savepoints, and isolation levels with simple diagrams and C# examples.
The Real Cost of Returning the Identity Value in EF Core
Why EF Core asking the database for the new Id after every insert costs round trips, and how HiLo, sequences, and Guids cut that cost down.
Soft Delete with EF Core: Delete Data Without Losing It
Learn soft delete in EF Core the right way. Use an interceptor and global query filters to hide deleted rows automatically, with simple examples, diagrams, code, and best practices for .NET 10.
Understanding Change Tracking for Better Performance in EF Core
Learn how EF Core change tracking works, the entity states it uses, and simple tricks like AsNoTracking to make your .NET apps faster.