Stored procedure vs view in SQL Server: which one to use

Views are saved queries you can select from; stored procedures are programs you execute. How they differ in parameters, performance, security and updates, with examples.

By Areeb Ahmer, . 4 minute read.

A view is a saved SELECT that behaves like a table: you query it, join it and filter it. A stored procedure is a saved program: you execute it with parameters, and it can do anything from returning rows to changing several tables in a transaction.

They overlap only in one case, “give me some rows”, and that’s where people wonder which to pick. The examples run against the SpDevDemo database.

The same rows, two ways

CREATE OR ALTER VIEW dbo.OpenOrders
AS
SELECT o.OrderId, o.OrderNumber, o.OrderDate, o.Total, c.CustomerId, c.Name AS CustomerName, c.Country
FROM dbo.Orders AS o
JOIN dbo.Customers AS c ON c.CustomerId = o.CustomerId
WHERE o.Status = 'Open';
GO

CREATE OR ALTER PROCEDURE dbo.GetOpenOrdersByCountry
    @Country CHAR(2)
AS
BEGIN
    SET NOCOUNT ON;
    SELECT o.OrderId, o.OrderNumber, o.OrderDate, o.Total, c.CustomerId, c.Name AS CustomerName
    FROM dbo.Orders AS o
    JOIN dbo.Customers AS c ON c.CustomerId = o.CustomerId
    WHERE o.Status = 'Open' AND c.Country = @Country;
END

The view is used like a table, and the caller adds whatever it needs:

SELECT Country, COUNT(*) AS OpenOrders, SUM(Total) AS Value
FROM dbo.OpenOrders
GROUP BY Country
ORDER BY Value DESC;

The procedure is executed, and returns exactly what it was written to return:

EXEC dbo.GetOpenOrdersByCountry @Country = 'PK';

How they differ

View Stored procedure
Used as A table, in FROM and JOIN A command, with EXEC
Parameters None Yes
Logic One SELECT Any T-SQL: variables, IF, loops, several statements
Changes data Simple views can be updated through Yes, anything
Caller can filter, join, aggregate Yes No, unless it captures the rows first
Result shape Fixed columns One or more result sets
Plan Expanded into the caller’s query Compiled and cached per statement

Performance: a view is just its query

A (non-indexed) view stores no data and has no plan of its own. When you query it, SQL Server replaces the view’s name with its definition and optimizes the combined query. Filtering a view on Country = 'PK' is exactly as fast as writing that filter into the original query, because that’s what happens.

The trap is views stacked on views. Each level looks harmless, but the optimizer receives one enormous query, joins tables the outer query never needed, and runs out of time looking for a good plan. If you find a view selecting from three other views, flatten it.

A procedure’s statements are compiled when first run, and the plans are cached and reused, with the parameter sniffing that comes with that.

Indexed views: when a view does store data

Add a unique clustered index to a view created WITH SCHEMABINDING and SQL Server stores its result, keeping it up to date on every change to the base tables:

CREATE OR ALTER VIEW dbo.CustomerTotals
WITH SCHEMABINDING
AS
SELECT CustomerId, COUNT_BIG(*) AS Orders, SUM(Total) AS Spent
FROM dbo.Orders
GROUP BY CustomerId;
GO

CREATE UNIQUE CLUSTERED INDEX IX_CustomerTotals ON dbo.CustomerTotals (CustomerId);
GO

SET STATISTICS IO ON;
SELECT Orders, Spent FROM dbo.CustomerTotals WITH (NOEXPAND) WHERE CustomerId = 1;
SET STATISTICS IO OFF;
Table 'CustomerTotals'. Scan count 0, logical reads 2

Customer 1’s 20,000 orders, summed in 2 reads. The price is paid on writes: every insert, update and delete on dbo.Orders now also maintains the view. Indexed views have strict rules (COUNT_BIG(*) with GROUP BY, no outer joins, schema-qualified names, specific SET options). Outside Enterprise edition, query the view with WITH (NOEXPAND) so its index is used.

Security

Both are used to give access to data without giving access to the tables. Grant SELECT on a view, or EXECUTE on a procedure, and the user needs no permission on the tables underneath, as long as the view or procedure and the tables have the same owner (ownership chaining).

The difference is in what the user can do with it. A view lets them write any query over the columns you exposed. A procedure lets them run exactly one operation, with the parameters you allow.

Changing data through them

You can INSERT, UPDATE or DELETE through a simple view on one table, and SQL Server applies it to the table. Add WITH CHECK OPTION so changes can’t make a row disappear from the view. Anything more complex needs an INSTEAD OF trigger, and at that point a procedure is clearer.

Which one to use

  • Reusable shape of the data, which callers will filter, join or aggregate: a view.
  • A fixed operation with parameters, or anything that changes data: a stored procedure.
  • A view that needs parameters: an inline table-valued function. It’s a view with parameters, and it’s just as cheap.
  • An expensive aggregate read far more often than the data changes: an indexed view.

Many systems use both: views to define the shapes of the data, and procedures for the operations, reading from those views.