Another post for me that is simple and hopefully serves as an example for people trying to get blogging as #SQLNewBloggers.
Many people think that that an identity property will ensure a consistent, increasing numerical value. I ran across this tweet that indicates that situation.
This isn’t really true, for many reasons, but in this post I’ll look at the possible reasons we get gaps in identity values.
Let’s start with a basic table that contains an identity value. I’ll use this code:
CREATE TABLE dbo.SalesOrderHeader
( OrderKey INT IDENTITY(1, 1)
, CustomerName VARCHAR(30)
Now I can insert a few rows. Note that the results shown below the code will contain increasing values for the OrderKey.
INSERT dbo.SalesOrderHeader (CustomerName) VALUES ('Andy')
INSERT dbo.SalesOrderHeader (CustomerName) VALUES ('Brian')
INSERT dbo.SalesOrderHeader (CustomerName) VALUES ('Steve')
INSERT dbo.SalesOrderHeader (CustomerName) VALUES ('Anna')
Each of these inserts is a separate transaction, and they cause the identity to increment.
This is noted in the tweet as a cause, but let’s test this.
One of the common ways that we get gaps in identity values is when rows are deleted. Let’s remove the row with Steve in it.
I clearly have a gap in OrderKey here now. What happens if we add a new row? The identity value is built for (some) efficiency and doesn’t fill the gap. Only the next value is kept. We insert a row and get a 5.
As a side note, there is no index on this table, and no ORDER BY clause, so you can clearly see that there isn’t a reason why I should expect the ORDERKEY column to be returned in numerical or even insert order.
One of the more common occurrences with inserts is a problem with the value. For example, in this table, I have allocated 30 characters. What happens if I run this code?
INSERT dbo.SalesOrderHeader (CustomerName)
VALUES ('A Really Long Name Van Something The Third')
I get an error, which is shown here.
Checking the table, I have no value:
Let’s insert a new value and see.
We get a gap. The value “6” was skipped because of the error. The identity was allocated, but the rollback of the transaction due to the error did not rollback the identity sequence.
Reseeding the Property
One of the other ways to miss a value is directly reseeding the table. I can use the DBCC CHECKIDENT function to accomplish this. In my case, let’s run this code and set the identity value to 20.
DBCC CHECKIDENT(SalesOrderHeader, RESEED, 20)
Now I can insert new values and I’ll get these results.
The identity value was set to 20 and the next insert will increment this and take 21, leaving a gap from 8 to 20.
Don’t depend on the identity property to give you uniqueness, consecutive values, or avoid duplicates. It is up to you to code properly to account for these values.
This post came about from helping someone understand the problems and limitations. I wrote this in about 20 minutes (with setup and testing) to ensure that I understood what I was explaining to someone.
You could write something similar to show that you know the ways in which identity works.