I have been writing a weekly round up from my blog where I go over last six years of blog posts and pick the best posts from the pasts. While I do this, there are two major places where I focus:
- If there are changes in features – I re-blog about it with additional details or
- If I have not provided complete information six years ago, I try to fill up the gap now. Well, just like everything, my knowledge and writing skills have evolved.
Before continuing, please read my latest memory lane blog post where in 2007 I wrote scripts for Primary Key and Unique Key.
November 2006 was when I started to learn more about SQL and had been only 4 months in the product, I was still exploring various subjects. I wrote a blog post describing about how Primary Key and Unique Key are different. Everything that I wrote there is correct, however, there are a few more details one should learn when it is about Primary Key and Clustered Index.
Here is the common misconception prevailing in the industry.
Primary Key has to be Clustered Index.
In reality, the statement should be corrected as follows:
Primary Key can be Clustered or Non-clustered, but it is a common best practice to create a Primary Key as Clustered Index.
Well, now we have corrected the statement. Let us understand a bit more in detail. Primary Key should be uniquely identifying column of the table and it should be NOT NULL
. A good (most of the time) candidate of the clustered index key also uniquely identifies column and NOT NULL
(most of the time). Well, that means it is a good idea to create a Primary Key Clustered so it solves both the problems together. Keeping these facts in mind, SQL Server automatically creates Clustered Index on the Primary Key when the table is created. Developers often do not specify which column should have clustered index so by default Primary Key becomes Clustered Index. This practice is now extremely common and lots of people have forgotten that Primary Key and Clustered Index is two different things. They can be the same column but they do not have to be.
Well, here are four examples we will see where we will learn the behavior of SQL Server when it is about Primary Key and Clustered Index.
- Scenario 1: Primary Key will default to Clustered Index
- Scenario 2: Primary Key is defined as a Non-clustered Index
- Scenario 3: Primary Key defaults to Non-Clustered Index with another column defined as a Clustered Index
- Scenario 4: Primary Key defaults to Clustered Index with other index defaults to Non-clustered index
Now let us see each of the scenarios in detail.
Scenario 1: Primary Key will Default to Clustered Index
In this case, we will create only Primary Key and when we check the kind of index created on the table, we will notice that it has created clustered index automatically over it.
USE TempDB
GO
CREATE TABLE TestTable
(ID INT NOT NULL PRIMARY KEY,
Col1 INT NOT NULL)
GO
SELECT OBJECT_NAME(OBJECT_ID) TableObject,
[name] IndexName,
[Type_Desc]
FROM sys.indexes
WHERE OBJECT_NAME(OBJECT_ID) = 'TestTable'
GO
DROP TABLE TestTable
GO
Scenario 2: Primary Key is Defined as a Non-clustered Index
In this case, we will explicitly define Primary Key as a non-clustered index and it will create it as a non-clustered index. It proves that Primary Key can be a non-clustered index.
USE TempDB
GO
CREATE TABLE TestTable
(ID INT NOT NULL PRIMARY KEY NONCLUSTERED,
Col1 INT NOT NULL)
GO
SELECT OBJECT_NAME(OBJECT_ID) TableObject,
[name] IndexName,
[Type_Desc]
FROM sys.indexes
WHERE OBJECT_NAME(OBJECT_ID) = 'TestTable'
GO
DROP TABLE TestTable
GO
Scenario 3: Primary Key Defaults to Non-Clustered Index with Another Column Defined as a Clustered Index
In this case, we will create clustered index on another column, SQL Server will automatically create a Primary Key as a non-clustered index as clustered index is specified on another column.
USE TempDB
GO
CREATE TABLE TestTable
(ID INT NOT NULL PRIMARY KEY,
Col1 INT NOT NULL UNIQUE CLUSTERED)
GO
SELECT OBJECT_NAME(OBJECT_ID) TableObject,
[name] IndexName,
[Type_Desc]
FROM sys.indexes
WHERE OBJECT_NAME(OBJECT_ID) = 'TestTable'
GO
DROP TABLE TestTable
GO
Scenario 4: Primary Key Defaults to Clustered Index with Other Index Defaults to Non-clustered Index
In this case, we will create two indexes on both the tables, but we will not specify the type of the index on the columns. When we check the results, we will notice that Primary Key is automatically defaulted to Clustered Index and another column as a Non-clustered index.
USE TempDB
GO
CREATE TABLE TestTable
(ID INT NOT NULL PRIMARY KEY,
Col1 INT NOT NULL UNIQUE)
GO
SELECT OBJECT_NAME(OBJECT_ID) TableObject,
[name] IndexName,
[Type_Desc]
FROM sys.indexes
WHERE OBJECT_NAME(OBJECT_ID) = 'TestTable'
GO
DROP TABLE TestTable
GO
I think the above examples clarify if there is any confusion related to Primary and Clustered Index.
Now here is the question I often get asked: what can be the reason for creating Primary Key and Clustered Index Key on different columns. Well, there are many scenarios when this can be true. It is possible that you have column SSN
which you want to create as a Primary Key but do not want make it as a clustered index key because you have uniquely increasing identity column which best suits your need for that table (again, this is just an example – you can argue exactly the opposite way as well). You are welcome to continue the discussion on this subject in the comments field or a dedicated blog post I wrote about it years ago over here. There are few really good comments there – I think that blog post is now a gold mine to understand this concept.
Reference