Published on

September 2, 2010

Understanding the Limitations of Views in SQL Server

Views are a powerful feature in SQL Server that allow you to create virtual tables based on the result of a query. They provide a way to simplify complex queries and encapsulate logic for reuse. However, there are certain limitations that you need to be aware of when working with views in SQL Server.

1. COUNT(*) Limitation

One of the most prominent limitations of views is that they do not support the use of COUNT(*). However, you can use the COUNT_BIG(*) operator instead. For example, if a view contains COUNT(*), it cannot have a clustered index on it. But if you change the COUNT(*) to COUNT_BIG(*), a similar index can be created.

Let’s take a look at an example:

USE tempdb
GO

IF EXISTS (SELECT * FROM sys.views WHERE OBJECT_ID = OBJECT_ID(N'[dbo].[SampleView]'))
    DROP VIEW [dbo].[SampleView]
GO

IF EXISTS (SELECT * FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'[dbo].[mySampleTable]') AND TYPE IN (N'U'))
    DROP TABLE [dbo].[mySampleTable]
GO

-- Create SampleTable
CREATE TABLE mySampleTable (
    ID1 INT,
    ID2 INT,
    SomeData VARCHAR(100)
)

INSERT INTO mySampleTable (ID1, ID2, SomeData)
SELECT TOP 100000 ROW_NUMBER() OVER (ORDER BY o1.name), ROW_NUMBER() OVER (ORDER BY o2.name), o2.name
FROM sys.all_objects o1
CROSS JOIN sys.all_objects o2
GO

-- Create View
CREATE VIEW SampleView WITH SCHEMABINDING AS
SELECT COUNT(*) TableCount, ID2
FROM dbo.mySampleTable
GROUP BY ID2
GO

-- Create Index on View
CREATE UNIQUE CLUSTERED INDEX [IX_ViewSample] ON [dbo].[SampleView] (ID2 ASC)
GO

/* Above statement will throw an error:
Msg 10136, Level 16, State 1, Line 1
Cannot create index on view "tempdb.dbo.SampleView" because it uses the aggregate COUNT. Use COUNT_BIG instead. */

-- Alter View to replace COUNT with COUNT_BIG
ALTER VIEW SampleView WITH SCHEMABINDING AS
SELECT COUNT_BIG(*) TableCount, ID2
FROM dbo.mySampleTable
GROUP BY ID2
GO

-- Now let us create Index again - this time successfully
CREATE UNIQUE CLUSTERED INDEX [IX_ViewSample] ON [dbo].[SampleView] (ID2 ASC)
GO

In the above example, we first create a table called “mySampleTable” and populate it with some data. Then, we create a view called “SampleView” that uses COUNT(*) to calculate the table count for each ID2 value. However, when we try to create a clustered index on the view, it throws an error because COUNT(*) is not supported. We then alter the view to use COUNT_BIG(*) instead, and this time we are able to create the index successfully.

2. Explanation of COUNT_BIG vs COUNT

You might be wondering why SQL Server allows the use of COUNT_BIG and not just COUNT. Itzik Ben-Gan, a renowned SQL Server expert, explains the reason behind this in his book series, ‘Inside T-SQL’.

When a query is grouped, SQL Server needs to keep track of the count in each group in order to determine whether a group needs to be modified or removed upon DELETE or UPDATE operations on the underlying tables. The use of COUNT_BIG instead of COUNT is related to the support for groups with more rows than the maximum four-byte integer.

It’s worth noting that this limitation is not specific to views but applies to grouped queries in general. If you try to add more rows to a table that has an indexed view and SQL Server rejects the insert due to a four-byte integer overflow in the target group count, you will encounter error 666.

If you want to learn more about this topic, I highly recommend reading Itzik Ben-Gan’s book, ‘Inside T-SQL’.

These are just a couple of limitations of views in SQL Server. It’s important to be aware of these limitations and consider them when designing your database schema and writing queries.

I hope you found this article helpful in understanding the limitations of views in SQL Server. Let me know your thoughts and if you have any other opinions or examples to share.

Click to rate this post!
[Total: 0 Average: 0]

Let's work together

Send us a message or book free introductory meeting with us using button below.