Why is Identity Seed showing the wrong value in SQL Server? - sql-server

I have set the seed value from 1 to 100 using the below command, but SQL Server still shows 1 as an Identity Seed value, It should be.
DBCC CHECKIDENT (TableName, RESEED, 100);
When I run this SELECT IDENT_SEED('TableName') , it still shows 1, In design also it is showing 1.
When I insert the records the tables, its getting inserted properly, I mean after 100 only.
SSMS Version: 18.4

IDENT_SEED doesn't return the current seed of the table, what you have is working. From IDENT_SEED (Transact-SQL):
Returns the original seed value specified when creating an identity column in a table or a view. Changing the current value of an identity column by using DBCC CHECKIDENT doesn't change the value returned by this function.
Emphasis mine.
If you want to check the current seed, then follow the instructions in DBCC CHECKIDENT: DBCC CHECKIDENT (N'dbo.YourTable', NORESEED);.
Example:
USE Sandbox;
GO
CREATE TABLE dbo.IdentID (ID int IDENTITY(1,1));
GO
INSERT INTO dbo.IdentID
DEFAULT VALUES;
GO
--Returns 1
SELECT *
FROM dbo.IdentID;
GO
--Returns 1
SELECT IDENT_SEED(N'dbo.IdentID') AS IDENTSEED;
GO
--Returns 1 for identity value, as it gives the last used value
DBCC CHECKIDENT (N'dbo.IdentID', NORESEED);
GO
DBCC CHECKIDENT (N'dbo.IdentID', RESEED, 100);
GO
--Returns 1
SELECT IDENT_SEED(N'dbo.IdentID') AS IDENTSEED;
GO
--Returns 100 for identity value
DBCC CHECKIDENT (N'dbo.IdentID', NORESEED);
GO
INSERT INTO dbo.IdentID
DEFAULT VALUES;
GO
--Returns rows with IDs of 1 and 101
SELECT *
FROM dbo.IdentID;
GO
GO
DROP TABLE dbo.IdentID;

Related

Weird behavior of DBCC CHECKIDENT with RESEED in a rolled-back transaction

Consider the following T-SQL code (the code is available along with an ADO.NET version in this GitHub repo https://github.com/PaloMraz/SqlServerReseedSampleApp):
DROP TABLE IF EXISTS __Test;
CREATE TABLE __Test (Id INT IDENTITY NOT NULL PRIMARY KEY);
GO
BEGIN TRAN;
SET IDENTITY_INSERT __Test ON;
INSERT INTO __Test (Id) VALUES (100);
SET IDENTITY_INSERT __Test OFF;
DBCC CHECKIDENT('__Test', RESEED, 1);
ROLLBACK TRAN;
GO
SELECT IDENT_CURRENT('__Test'); -- returns 100 instead of 1
The code does the following:
Creates a __Test table with IDENTITY column.
Starts a transaction.
INSERTs new row overriding the IDENTITY seed value to 100.
Reseeds the IDENTITY back to 1.
Rolls back the transaction.
Queries the current identity.
I have expected, that the current identity value will be back at 1, but instead, it is 100. This means that the transaction rolled back the inserted row and the results of the DBCC CHECKIDENT command, but did not roll back the overridden IDENTITY seed!
Is this the correct behavior? Why?
Thank you for your time!
The only real question here is why DBCC CHECKIDENT ... RESEED can be rolled back. With IDENTITY INSERT or not inserting into a table with an IDENTITY column will increment the current identity value without blocking other sessions' ability to generate new IDENTITY values. To do this, the modification of the current IDENTITY value must not be enlisted in the session's transaction.
DBCC CHECKIDENT is effectively a DDL statement, like ALTER TABLE. It requires an exclusive metadata lock on the object, and therefore can be committed or rolled back. EG
BEGIN TRAN;
DBCC CHECKIDENT('__Test', RESEED, 100);
select *
from sys.dm_tran_locks
where request_session_id = ##spid
ROLLBACK TRAN;
Will show Sch-M locks on the target table.
More interesting ...
DROP TABLE IF EXISTS __Test;
CREATE TABLE __Test (Id INT IDENTITY NOT NULL PRIMARY KEY, Name nvarchar(100));
GO
BEGIN TRAN;
INSERT INTO __Test (Name) VALUES ('A');
INSERT INTO __Test (Name) VALUES ('B');
DBCC CHECKIDENT('__Test', RESEED, 100);
INSERT INTO __Test (Name) VALUES ('C');
SELECT IDENT_CURRENT('__Test'); -- Returns 101
ROLLBACK TRAN;
GO
SELECT IDENT_CURRENT('__Test'); -- Return 2

DBCC CHECKIDENT(myTable, RESEED,1) reseeding from 2

In SQL Server 2012, the following query is seeding the identity column myTable_id from 2 instead of 1. Why? myTable_id is also PK.
DELETE FROM myTable;
GO
SELECT * FROM myTable --0 rows are returned as expected
GO
DBCC CHECKIDENT(myTable, RESEED,1)
GO
INSERT INTO myTable(col1,col2,col3) SELECT FROM AnotherTable(col1,col2,col3)
GO
SELECT * FROM myTable --1005 rows are returned as expected, but identity value starts from 2
GO
Remark:
The data inserted is right, the only issue is that the newly inserted data starts from 2 instead of 1.
In the above sql code if I use DBCC CHECKIDENT(myTable, RESEED,0) the identity column correctly starts from 1.
Following is snapshot in SSMS for the myTable_id column:
From the docs:
The seed value is the value inserted into an identity column for the very first row loaded into the table. All subsequent rows contain the current identity value plus the increment value where current identity value is the last identity value generated for the table or view.
So if you seed from 10, the next value to be inserted will be 11.
There is nothing bad with the answer here but the confusion comes from Microsoft approach itself.
I think that:
DBCC CHECKIDENT(myTable, RESEED, 0)
Should have the same behavior everywhere:
on new created table,
after delete table records,
after truncating the table
Otherwise we need to check the table status before running this.
Works as expected see also
https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-checkident-transact-sql#examples
The value 1 means that the current identity will be at 1 and the next identity will start on 2
To get it starting on 1 you should do
DBCC CHECKIDENT(myTable, RESEED, 0)
This does the trick for me:
DBCC CHECKIDENT ([Table], RESEED, 0)
DBCC CHECKIDENT ([Table], RESEED)

Auto-increment column in SQL Server does not always start at 1?

I am using SqlServer 2005 and I have a table in which I have an auto incrementing column but for some reason the auto increment field does not start with 1 but with some random number like 21,91. Why does that happen?
You either need to set the Seed for the column.... or if you had entered rows previously, you need to execute a TRUNCATE TABLE command on the table...
TRUNCATE TABLE XYZ
mssql is not using max(id) + 1 as identity like other databases. It is storing the last used id and is incrementing it.
You can reseed the identity:
DBCC CHECKIDENT ('tablex', RESEED, 1)
or truncate the table, this is also deleting all the data:
TRUNCATE TABLE tablex
You can of course combine the identity reseed with the last value:
DBCC CHECKIDENT ('tablex', RESEED, (SELECT max(id) + 1 FROM tablex))
But be aware of producing errors on reseeding the id due to conflicts, the auto increment id is unique!

Insert data in to sql server data table

I have one table called customer_master that includes a column called cust_id with autoincrement set to 1.
When we try to insert records its working fine and inserted records like cust_id 1, 2, 3 and 4 are inserted, but when an error is generated in the insert command we do a transaction rollback, this means that cust_id 5 is not inserted, but when we are insert another record, cust_id generates 6. It skips cust_id 5.
I want to set it up so that if any error is generated in the insert command the identity is not incremented.
We are using c# and sql server 2005.
The reason SQL Server does this is for efficiency. If you need a sequence number without gaps you shouldn't be using identity you would need to implement your own scheme where concurrent transactions are blocked waiting for the next value just in case the initial transaction rolls back.
The second query here could be used for that purpose. But do you really need this? If it is purely for aesthetic purposes my advice is not to worry about it!
You can use DBCC CHECKIDENT to reseed the identity column after an insert failure.
DBCC CHECKIDENT ( table_name, NORESEED ) returns the current identity value and the current maximum value of the identity column.
DBCC CHECKIDENT ( table_name, RESEED, new_reseed_value ) sets the current identity value to the new_reseed_value.

Reset AutoIncrement in SQL Server after Delete

I've deleted some records from a table in a SQL Server database.
The IDs in the table look like this:
99
100
101
1200
1201...
I want to delete the later records (IDs >1200), then I want to reset the auto increment so the next autogenerated ID will be 102. So my records are sequential, Is there a way to do this in SQL Server?
Issue the following command to reseed mytable to start at 1:
DBCC CHECKIDENT (mytable, RESEED, 0)
Read about it in the Books on Line (BOL, SQL help). Also be careful that you don't have records higher than the seed you are setting.
DBCC CHECKIDENT('databasename.dbo.tablename', RESEED, number)
if number = 0 then in the next insert the auto increment field will contain value 1
if number = 101 then in the next insert the auto increment field will contain value 102
Some additional info... May be useful to you
Before giving auto increment number in above query, you have to make sure your existing table's auto increment column contain values less that number.
To get the maximum value of a column(column_name) from a table(table1), you can use following query
SELECT MAX(column_name) FROM table1
semi idiot-proof:
declare #max int;
select #max = max(key) from table;
dbcc checkident(table,reseed,#max)
http://sqlserverplanet.com/tsql/using-dbcc-checkident-to-reseed-a-table-after-delete
If you're using MySQL, try this:
ALTER TABLE tablename AUTO_INCREMENT = 1
I figured it out. It's:
DBCC CHECKIDENT ('tablename', RESEED, newseed)
Delete and Reseed all the tables in a database.
USE [DatabaseName]
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all" -- Disable All the constraints
EXEC sp_MSForEachTable "DELETE FROM ?" -- Delete All the Table data
Exec sp_MSforeachtable 'DBCC CHECKIDENT(''?'', RESEED, 0)' -- Reseed All the table to 0
Exec sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all" -- Enable All the constraints back
-- You may ignore the errors that shows the table without Auto increment field.
Based on the accepted answer, for those who encountered a similar issue, with full schema qualification:
([MyDataBase].[MySchemaName].[MyTable])... results in an error, you need to be in the context of that DB
That is, the following will throw an error:
DBCC CHECKIDENT ([MyDataBase].[MySchemaName].[MyTable], RESEED, 0)
Enclose the fully-qualified table name with single quotes instead:
DBCC CHECKIDENT ('[MyDataBase].[MySchemaName].[MyTable]', RESEED, 0)
Several answers recommend using a statement something like this:
DBCC CHECKIDENT (mytable, RESEED, 0)
But the OP said "deleted some records", which may not be all of them, so a value of 0 is not always the right one. Another answer suggested automatically finding the maximum current value and reseeding to that one, but that runs into trouble if there are no records in the table, and thus max() will return NULL. A comment suggested using simply
DBCC CHECKIDENT (mytable)
to reset the value, but another comment correctly stated that this only increases the value to the maximum already in the table; this will not reduce the value if it is already higher than the maximum in the table, which is what the OP wanted to do.
A better solution combines these ideas. The first CHECKIDENT resets the value to 0, and the second resets it to the highest value currently in the table, in case there are records in the table:
DBCC CHECKIDENT (mytable, RESEED, 0)
DBCC CHECKIDENT (mytable)
As multiple comments have indicated, make sure there are no foreign keys in other tables pointing to the deleted records. Otherwise those foreign keys will point at records you create after reseeding the table, which is almost certainly not what you had in mind.
I want to add this answer because the DBCC CHECKIDENT-approach will product problems when you use schemas for tables. Use this to be sure:
DECLARE #Table AS NVARCHAR(500) = 'myschema.mytable';
DBCC CHECKIDENT (#Table, RESEED, 0);
If you want to check the success of the operation, use
SELECT IDENT_CURRENT(#Table);
which should output 0 in the example above.
You do not want to do this in general. Reseed can create data integrity problems. It is really only for use on development systems where you are wiping out all test data and starting over. It should not be used on a production system in case all related records have not been deleted (not every table that should be in a foreign key relationship is!). You can create a mess doing this and especially if you mean to do it on a regular basis after every delete. It is a bad idea to worry about gaps in you identity field values.
What about this?
ALTER TABLE `table_name`
MODIFY `id` int(12) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0;
This is a quick and simple way to change the auto increment to 0 or whatever number you want. I figured this out by exporting a database and reading the code myself.
You can also write it like this to make it a single-line solution:
ALTER TABLE `table_name` MODIFY `id` int(12) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0;
To reset every key in the database to autoincrement from the max of the last highest key:
Exec sp_MSforeachtable 'DBCC CHECKIDENT(''?'', RESEED, 0)'
Exec sp_MSforeachtable 'DBCC CHECKIDENT(''?'', RESEED)'
If you just want to reset the primary key/sequence to start with a sequence you want in a SQL server, here's the solution -
IDs:
99 100 101 1200 1201...
Drop rows with IDs >= 1200. (Be careful if you have foreign key constraints tied to these which has to be dealed with or deleted too to be able to delete this.)
Now you want to make sure you know the MAX ID to be sure:
declare #max_id as int = (SELECT MAX(your_column_name) FROM
your_table)+1;
(Note: +1 to start the ID sequence after max value)
Restart your sequence:
exec('alter sequence your_column_name restart with ' + #max_id);
(Note: Space after with is necessary)
Now new records will start with 102 as the ID.
I know this is an old question. However, I was looking for a similar solution for MySQL and this question showed up.
for those who are looking for MySQL solution, you need to run this query:
// important!!! You cannot reset the counter to a value less than or equal to the value that is currently in use. For both InnoDB and MyISAM, if the value is less than or equal to the maximum value currently in the AUTO_INCREMENT column, the value is reset to the current maximum AUTO_INCREMENT column value plus one.
ALTER TABLE <your-table-name> AUTO_INCREMENT = 100
documentation

Resources