Views
Learn how to create and query SQL Server views, and why they are so useful for simplifying complex or frequently repeated queries.
Introduction
As your database grows, you will often find yourself writing the same complex query - joining several tables and filtering rows in a very specific way - over and over again in reports, applications, and ad-hoc queries. A view lets you save that query under a name and reuse it as if it were a regular table. In this lesson, you will learn what a view is, how to create one, and why views are one of the most practical tools for keeping T-SQL code clean and consistent.
- What a view is and how it differs from a table.
- How to create a view with CREATE VIEW.
- How to query a view exactly like a table.
- When a view can be updated, and when it cannot.
- How to alter and drop views safely.
Why Use Views?
A view is a virtual table backed by a stored SELECT statement. It does not store data itself (unless you create an indexed view, a more advanced topic); instead, every time you query the view, SQL Server runs the underlying query and returns the results. Views are useful for several reasons: they hide complexity behind a simple name, they let you expose only certain columns or rows to certain users, and they keep business logic consistent because everyone queries the same definition instead of copying and pasting SQL.
| Situation | Why a View Helps |
|---|---|
| A report joins 5 tables every time | Wrap the join once in a view; reports just SELECT FROM the view |
| Users should only see active customers | The view can filter WHERE IsActive = 1, hiding inactive rows |
| A table has sensitive columns | The view can expose only the safe columns, hiding others |
| Multiple apps need the same calculated column | Define the calculation once in the view instead of duplicating it |
Creating a View
You create a view with CREATE VIEW followed by a name and an AS clause containing a SELECT statement. The example below assumes a Customers table with an IsActive flag.
CREATE VIEW dbo.vwActiveCustomers ASSELECT CustomerID, FirstName, LastName, Email, CityFROM dbo.CustomersWHERE IsActive = 1;GOCREATE VIEW must be the first statement in its batch. If you are running this in the same script as other statements, put GO on the line before CREATE VIEW to start a new batch.
Querying a View
Once created, you query a view exactly like a table - with SELECT, WHERE, ORDER BY, and even joins to other tables.
SELECT CustomerID, FirstName, LastName, CityFROM dbo.vwActiveCustomersWHERE City = 'Seattle'ORDER BY LastName;Click Run to see what this code prints.
Views Over Joins
Views are especially valuable when the underlying query involves multiple joins. Instead of every report re-writing the join logic, they simply select from the view.
CREATE VIEW dbo.vwOrderSummary ASSELECT o.OrderID, c.FirstName + ' ' + c.LastName AS CustomerName, o.OrderDate, SUM(od.Quantity * od.UnitPrice) AS OrderTotalFROM dbo.Orders oJOIN dbo.Customers c ON c.CustomerID = o.CustomerIDJOIN dbo.OrderDetails od ON od.OrderID = o.OrderIDGROUP BY o.OrderID, c.FirstName, c.LastName, o.OrderDate;GO
SELECT TOP 3 * FROM dbo.vwOrderSummary ORDER BY OrderTotal DESC;Click Run to see what this code prints.
Updatable Views
A view built on a single table with no aggregates, DISTINCT, GROUP BY, or set operators is generally updatable - you can run INSERT, UPDATE, or DELETE against it and SQL Server applies the change to the base table. dbo.vwActiveCustomers is a good example, since it comes from a single table with simple columns.
UPDATE dbo.vwActiveCustomersSET City = 'Redmond'WHERE CustomerID = 104;dbo.vwOrderSummary joins three tables and uses GROUP BY, so SQL Server will reject direct INSERT/UPDATE/DELETE statements against it. For views like that, treat them as read-only reporting views.
Altering and Dropping Views
Use ALTER VIEW to change a view's definition without dropping and recreating any permissions granted on it, and DROP VIEW to remove it entirely.
ALTER VIEW dbo.vwActiveCustomers ASSELECT CustomerID, FirstName, LastName, Email, City, CountryFROM dbo.CustomersWHERE IsActive = 1;GO
DROP VIEW IF EXISTS dbo.vwOldReport;Common Mistakes
- Using SELECT * inside a view definition - if columns are later added to the base table, the view's behavior can silently change.
- Nesting views many layers deep, which makes the actual query plan hard to reason about and can hurt performance.
- Assuming every view is updatable - views with joins, GROUP BY, or DISTINCT are not.
- Forgetting that a view does not store data (unless indexed), so querying it still costs the same as the underlying query.
- Not granting SELECT permission on the view itself when trying to hide the base tables from a user.
Best Practices
- List columns explicitly in a view instead of using SELECT *.
- Use a consistent naming prefix like vw for views so they are easy to spot in object lists.
- Use views to enforce row-level and column-level security instead of granting direct table access.
- Keep views focused on one purpose - a reporting view and a security view can be separate objects.
- Document non-obvious business logic (like which rows count as 'active') directly in the view so it is defined in one place.
Frequently Asked Questions
Not by itself. SQL Server expands the view's definition into the outer query at execution time, so performance depends on the underlying query and indexes, not on the fact that a view was used.
Yes, but keep nesting shallow. Deeply nested views make it harder to predict the final execution plan and to debug unexpected results.
An indexed (or 'materialized') view has a unique clustered index built on it, which physically stores the result set and can speed up expensive aggregations. It is a more advanced, more restrictive feature covered separately from ordinary views.
No - views cannot take parameters. If you need parameterized, reusable logic, use an inline table-valued function instead, which behaves like a parameterized view.
Key Takeaways
- A view is a saved SELECT statement that you can query like a table.
- Views simplify complex or repeated queries and can hide columns or rows for security.
- Single-table views without aggregates are usually updatable; multi-table views generally are not.
- Views do not store data on their own, so their performance depends on the underlying query.
- Use ALTER VIEW to change a definition and DROP VIEW to remove it.
Summary
Views let you package a query once and reuse it everywhere, which keeps reporting logic consistent and can simplify what end users and applications need to know about your schema. Next, you will look at indexes - one of the most important tools for making those queries (view-based or not) run fast.