问题
My table works fine if I enter data correctly - I can insert data and the IDENTITY values are 1, 2, 3, 4. However, if I make a mistake and get an error message, e.g.
Cannot insert the value NULL into column 'x', table 'table'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Then if I insert another row successfully, the IDENTITY value is 6, not 5.
How can I solve this problem?
回答1:
Well, first:
This is not a problem.
The "problem" is very, very much by design.
Do not, I repeat, do not expect IDENTITY columns to maintain a nice, contiguous set of values, with no gaps. You really shouldn't care if there are gaps, but they can be caused by all kinds of things. Deletes, rollbacks, failovers and service restarts, etc. Stop worrying about the value and trying to prevent gaps; IDENTITY works efficiently precisely because SQL Server doesn't do all the extra work that would be required to prevent gaps. If you want to do that, you'll have to roll your own solution manually.
Oh, and reseeding is not an option. Here's why. First, let's take an example where the table has no primary key (or at least the primary key is not on the IDENTITY column):
CREATE TABLE dbo.foo(id INT IDENTITY(1,1));
GO
INSERT dbo.foo DEFAULT VALUES;
GO 5
DBCC CHECKIDENT('dbo.foo', reseed, 0);
INSERT dbo.foo DEFAULT VALUES;
GO
SELECT id FROM dbo.foo ORDER BY id;
GO
DROP TABLE dbo.foo;
Results:
id
----
1
1 <-- oops! Duplicate. We probably didn't want that, right?
2
3
4
5
Now, if the IDENTITY column is also the primary key (pretty common):
CREATE TABLE dbo.foo(id INT IDENTITY(1,1) PRIMARY KEY);
GO
INSERT dbo.foo DEFAULT VALUES;
GO 5
DBCC CHECKIDENT('dbo.foo', reseed, 0);
GO
INSERT dbo.foo DEFAULT VALUES;
GO
DROP TABLE dbo.foo;
Oops:
Msg 2627, Level 14, State 1, Line 7
Violation of PRIMARY KEY constraint 'PK_foo_3213E83FE3F1E24C'. Cannot insert duplicate key in object 'dbo.foo'. The duplicate key value is (1).
The statement has been terminated.
So what do you propose to do there? Loop until you no longer get an exception? Write all kinds of convoluted gaps and islands code that finds the first gap, then SET IDENTITY_INSERT ON;
and manually insert values? Why? What did you gain? Slow down the march to 2 billion and an overflow? I don't understand this obsession with sequential numbers and no gaps in an IDENTITY column. It's a surrogate, meaningless value. Let me repeat once more:
Gaps are not a problem.
The problem isn't the technique. The problem is worrying about gaps in the first place. If you care about gaps, stop trying to figure out how to use IDENTITY to prevent them; just stop using IDENTITY, period. Or stop caring about gaps.
来源:https://stackoverflow.com/questions/19597781/why-are-there-gaps-in-my-identity-column