I am using SQL Server Express and VS2008.
I have a database with a table A, which has a column ID as IDENTITY. The ID is auto-incremented. Even if the row is deleted, the ID still increases.
After several data manipulation, the current ID has reached 15, for example.
When I run the application
if there's at least 1 row: if I add a new row, the new ID is 16. Everything is fine.
If the table is empty (no row): if I add a new row, the new ID is 0, which is an error (I think).
And further data manipulation (e.g. delete or update) will result in an unhandled exception.
Has anyone encountered this?
PS. In my table definition, the ID has been selected as follow:
Identity Increment = 1; Identity Seed =1;
The DB load code is:
dataSet = gcnew DataSet();
dataAdapter->Fill(dataSet,"A");
dataTable=dataSet->Tables["A"];
dbConnection->Open();
The Update button method
dataAdapter->Update(dataSet,"tblInFlow");
dataSet->AcceptChanges();
dataTable=dataSet->Tables["tblInFlow"];
dataGrid->DataSource=dataTable;
If I press Update:
if there's at least a row: the datagrid view updates and shows the table correctly.
if there's nothing in the table (no data row), the Add method will add a new row, but from ID 0.
If I close the program and restart it again: the ID would be 16, which is correct.
This is the add method
row=dataTable->NewRow();
row["column1"]="something";
dataTable->Rows->Add(row);
dataAdapter->Update(dataSet,"A");
dataSet->AcceptChanges();
dataTable=dataSet->Tables["A"];
If you are deleting the date using
Delete from myTable
It will not reset the identity column but on the other hand if your truncating the table then it will reset any identity columns to the default seed value ( in your case starting from 1)
If you are truncating the table and then reseeding it ,the first identity reseed value will be 0 if you write
DBCC CHECKIDENT(MyTable, RESEED, 0)
Even though your identity column is specified as Identity=1 and seed =1 ,the very first row inserted will start from the Id=0
If you want to start from 1 then you need to reseed the column as
DBCC CHECKIDENT(MyTable, RESEED, 1)
Related
I created a table and inserted 4 rows into it. I ran the below query
SELECT seed_value as SeedValue, last_value as identityValue
FROM sys.identity_columns
WHERE object_id=OBJECT_ID('ALJtest1')
and got the result as
SeedValue| identityValue
-------------------------
1 | 4
Then I reseeded the table using
DBCC CHECKIDENT('DBO.ALJtest1', RESEED, 10)
When I ran the below query this time
SELECT seed_value as SeedValue, last_value as identityValue
FROM sys.identity_columns
WHERE object_id=OBJECT_ID('ALJtest1')
I got the result as
SeedValue| identityValue
-------------------------
1 | 10
Is there a way to find the last applied seed value on a table in SQL Server 2012?
RESEED, despite the name, doesn't change the identity's seed value, instead it simply sets the next identity value to generate. There is no way to change an identity column's actual seed value after it's created. From the documentation:
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.
You cannot use DBCC CHECKIDENT to perform the following tasks:
Change the original seed value that was specified for an identity column when the table or view was created.
Reseed existing rows in a table or view.
To change the original seed value and reseed any existing rows, you
must drop the identity column and recreate it specifying the new seed
value. When the table contains data, the identity numbers are added to
the existing rows with the specified seed and increment values. The
order in which the rows are updated is not guaranteed.
So to answer your question: no, there is no way to know the last value specified in a DBCC CHECKIDENT(..., RESEED), because the current identity value may have already changed after inserts.
I am using SQL Azure. I have a deployment DB and a test DB
I would like to add some new lookup records to the Test DB, to test new code.
Initially My Deployment DB's Identity was set to 200000+ for the PKs, and my Test DB to 100000+, to prevent PK collisions when syncing using such tools as Redgates' SQL data compare.
Unfortunately I made a mistake, and copied the Deployment DB as the new Test DB, since we required a more up to date dataset. As a result my Test DB now starts at 200000+. So I now have the risk of conflicts when syncing with the Deployment DB.
I would normallly just use:
DBCC CHECKIDENT('TableName', RESEED, 105000)
However SQL Azure does not support this.
I have come across a workaround:
set identity_insert TableName on -- this basically turns off IDENTITY
INSERT INTO TableName(id, name) VALUES (104999,'Test Reset Identity Start 104999') -- so we can jam any value for column ID
set identity_insert TableName off -- then turn it back on
INSERT INTO TableName(name) VALUES ('Test Reset Identity End') -- ID starts at 105000, in theory, from this point
SELECT * FROM TableName
However the new Identify value always seems to take the highest PK in the table as the last seed, rather than the PK value from the last inserted record.
I would rather not rebuild the table.
Is there another approach to resetting the identity value for my situation, ie to a lesser number ie 104999 rather the current 204999?
Thanks in advance.
EDIT 1
It may be I can only check the identity value to a value greater than the current value ie to say 206000 ?
EDIT 2
Perhaps there is an argument that Identity value should never be reseed to less than the max PK value, even if there is 100,000 spare numbers, as one day you will get a collision.
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.
I have a suite of database unit tests that were created. In order to replicate all of the tests on any machine I deploy out to there are scripts to drop the database and recreate it. The test will work for all of the unit tests except for the first test.
The reason the first test fails is that I am executing the "dbcc checkident" command before each test and resetting all of the identities in order to ensure that all of the identities are the same. On a new table that has never been inserted into and then has "dbcc checkident" ran against it the identity starts at 0 when inserted into instead of 1.
If I use some of the other built in commands to check the identity in a fresh table, they return 0 as the identity. The benefit for checking through "dbcc checkident" is that the identity comes back as 'NULL' if a row has never been inserted into it. Only "dbcc checkident" tells us through a print message and cannot easily be tested.
How can I verify that that I need to reset the identity or not through database commands without inserting a row, deleting it, then resetting just to avoid the identity from getting off on the first record?
Example of inserting into a table
Identity after inserting a row on a fresh table without running "dbcc checkident" and setting identity to 0 = 1
Identity after inserting a row on a fresh table and running "dbcc checkident" and setting identity to 0 = 0
Identity after inserting a row on an existing table thats been inserted into and running "dbcc checkident" and setting identity to 0 = 1
To get around the identity insert problem with "dbcc checkident" on a new table, here's what I did.
Using the sys tables I was able to manually check the last identity value through sql. If the last identity was reset, it will change the last value to 0. On a new table that has never been inserted into the last identity will be null.
Here is the code snippet we used. This will allow you to check the last identity without doing an insert, delete, reset identity.
-- {0} is your table name
-- {1} is your identity value of the reset
IF EXISTS (SELECT null FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = '{0}' AND last_value IS NOT NULL)
DBCC CHECKIDENT ({0}, RESEED, {1});
Is there any way of changing the identity seed for an identity column permanently? Using DBCC CHECKIDENT just seems to set the last_value. If the table is truncated all values are reset.
dbcc checkident ('__Test_SeedIdent', reseed, 1000)
select name, seed_value, increment_value, last_value
from sys.identity_columns
where [object_id] = OBJECT_ID('__Test_SeedIdent');
returns
name seed_value increment_value last_value
-------------------------------------------------
idIdent 1 1 1000
I was hoping that some syntax like
alter table dbo.__Test_SeedIdent alter column idIdent [int] identity(1000,1) NOT NULL
would exist.
Is it necessary to create a new column, move the values across, drop the original column and rename the new?
From Books Online:
"To change the original seed value and reseed any existing rows, you must drop the identity column and recreate it specifying the new seed value. When the table contains data, the identity numbers are added to the existing rows with the specified seed and increment values. The order in which the rows are updated is not guaranteed."
MSSQL does not allow you to add or alter an Identity on an existing column via TSQL very easily. You would have to drop the column and re-add it. Needless to say this can play hell with FK relations. You can do it directly in the enterprise manager. However that won't be fun if you have to do this to a LOT of columns.
Is it necessary to create a new
column, move the values across, drop
the original column and rename the
new?
Yup, and don't forget to fix/update all indexes, foreign key relationships, etc. that are tied to that column
You can use DBCC CHECKIDENT('tablename', RESEED, seedvalue)
example: DBCC CHECKIDENT('Customers',RESEED, 1350)
run DBCC CHECKIDENT('Customers') again to check if current seed value was set.
However as mentioned in previous answers this will not change existing values stored in the identity column. It will only change seed value so the next row that is inserted will start with that value. Identity increment remains same (not changed) and can not be changed with DBCC.
"Is it necessary to create a new column, move the values across, drop the original column and rename the new?"
Actually in Enterprise Manager, when you add an ID column to an existing table (or change an INT PK field to an INT PK ID), it does this behind the scene.