Inserting 100,000 rows at a time .. error identity column violation - sql

I'm trying to insert row by row in a table about 100k records.. I get this error after some 140 or so..
Violation of PRIMARY KEY constraint
'PK_table1'. Cannot insert duplicate
key in object 'table1'. The statement
has been terminated.
In this case the primary key is an IDENTITY column. I do not include that column in my INSERT statements.
I ran DBCC CHECKIDENT (table1,noreseed)
The current identity value and the current column value are NOT the same.
If I run the same command in 5 min, they become the same.
I cannot figure out what the problem is. Any help is greatly appreciated.

If the destination table is not empty then you want to reseed the identity column to the next highest existing value like so:
Declare #Max bigint
Set #Max = ( Select Max(IdCol) From TableA ) + 1
DBCC CHECKIDENT( TableA, RESEED, #Max )

You can use bcp command for this work. You can specify that identity being checked or not.

Related

SQL attempting to start an identity at a dynamic variable

In a nutshell, I have a temp table which stores a range of data. The number of rows could be dynamic depending on when this query is run. I'm then trying to alter the table and add an identity which I want to start at a defined value that I have chosen.
Whatever I seem to have tried, when viewing the data the identity column always starts at 1…and increments and not the value I specified.
--At this point of the code the data is already in the table!
Set existingNumber =
(
--Get a number from a table
)
Set existingNumber = existingNumber + 1
Alter table #myTable
Add testID bigINT Identity
DBCC CHECKIDENT (#myTable, RESEED, #existingNumber)
Is there a way that I can simply restart the Identity column for pre existing values?
I have tried looking at creating the identity with the table but this causes another problem due to how our company framework is unfortunately.
EDIT:
Using SQL Management Studio
Your #existingNumber variable is not being set correctly.
The below example works fine..
declare #existingNumber int = 1000
create table #test (col1 varchar(20))
alter table #test add testId bigint Identity
dbcc checkident (#test, reseed, #existingNumber)
insert into #test values ('test record')
select * from #test
drop table #test

Change Increment value for Identity - SQL Server 2005

I would like to change increment value of IDENTITY column in database and I have below restrictions:
Can't drop the column.
Having around 20k rows.
Dropping table and recreate table with changed increment value would be the solution. I don't know the syntax.
Can you please suggest the syntax or other best possible solution?
Thanks in Advance!
If i understand you correctly base on your response to my comment, you backed up the data of the orig table in temp table, then you deleted the orig table and you want to recreate an orig table.
If that is the case , you need the IDENTITY_INSERT to set ON and OFF, because the identity of the table is unique.
The syntax is:
SET IDENTITY_INSERT [TableName] ON -- set to on
-- Put your insert statement here
-- insert the data from backed up temp table to your new table
SET IDENTITY_INSERT [TableName] OFF -- set to off
If you can accept recreating table, there is no magic about the recreating table syntax.
CREATE TABLE temp_Table
(
-- Identity column with new settings
-- other columns
);
INSERT INTO temp_Table
SELECT -- Columns except identity column
FROM old_table;
DROP TABLE old_Table;
EXEC sp_rename 'temp_Table', 'old_Table';
However, you have to handle foreign key by yourself.
Altering identity column after table creation is not possible.
Instead, reset SEED value using the below command.
DBCC CHECKIDENT('tablename', RESEED, 15)

Reseeding Identity Column to Original Value

Is there any way to reseed an identity column to it's original value? Currently I have this IDENTITY(1,1) as my table definition. I've tried reseeding it using this method:
DBCC CHECKIDENT (Table1, reseed, 1)
But I noticed, that SQL actually reseeds it to current seed + the new seed value, so when I insert new rows it starts the auto-increment count at 2 instead of 1. I've also tried making the new reseed value 0, but then all the rows I insert after that end up being 1 and the column doesn't auto-increment anymore.
By the way, if it helps, I need this column to restart its auto-increment count at zero because I need for the count to restart every month. I have trigger after insert set up for this, but the reseeding is giving me some trouble.
The following statement:
DBCC CHECKIDENT('YourTableName', RESEED, 1);
Tells the database something akin to:
"Hey database! The highest identity value in the YourTableName table is #1, so the next inserted record should use identity value #2."
This explains is why your table starts with identity value 2 when you RESEED it using your statement.
More specifically Microsoft's help for DBCC CHECKIDENT() indicates:
Current identity value is set to the new_reseed_value. If no rows have been inserted to the table since it was created, or all rows have been removed by using the TRUNCATE TABLE statement, the first row inserted after you run DBCC CHECKIDENT uses new_reseed_value as the identity. Otherwise, the next row inserted uses new_reseed_value + the current increment value.
If the table is not empty, setting the identity value to a number less than the maximum value in the identity column can result in one of the following conditions:
If a PRIMARY KEY or UNIQUE constraint exists on the identity column, error message 2627 will be generated on later insert operations into the table because the generated identity value will conflict with existing values.
If a PRIMARY KEY or UNIQUE constraint does not exist, later insert operations will result in duplicate identity values.
It sounds like you want to change your table's initial starting seed value from 1 to 0. With this in mind, you need to modify the table's definition to use:
IDENTITY(0,1);
I hope this helps. Good luck.
Not really an answer, but too long for a comment and does cover the question.
I've also tried making the new reseed value 0, but then all the rows I insert after that end up being 1 and the column doesn't auto-increment anymore.
I can't reproduce this behaviour:
IF OBJECT_ID(N'dbo.T', 'U') IS NOT NULL
DROP TABLE dbo.T;
CREATE TABLE dbo.T(ID INT IDENTITY(1,1) NOT NULL);
INSERT dbo.T OUTPUT inserted.* DEFAULT VALUES;
-- OUTPUTS 1
DELETE dbo.T;
DBCC CHECKIDENT ('dbo.T', RESEED, 0);
INSERT dbo.T OUTPUT inserted.* DEFAULT VALUES;
-- OUTPUTS 1, I.E. RESEED TO 0 HAS WORKED FINE
INSERT dbo.T OUTPUT inserted.* DEFAULT VALUES;
-- OUTPUTS 2, SHOWS INCREMENT IS WORKING AS EXPECTED
IF OBJECT_ID(N'dbo.T', 'U') IS NOT NULL
DROP TABLE dbo.T;
It is worth noting however that for an empty table the identity will start at 0 if you use 0 as the RESEED value, i.e.
TRUNCATE TABLE dbo.T;
DBCC CHECKIDENT ('dbo.T', RESEED, 0);
INSERT dbo.T OUTPUT inserted.* DEFAULT VALUES;
Will output 0 as the ID inserted.
I believe the only way to do this would be to select all your data into a 2nd table.
Then you can issue the command truncate table Table1.
This will reset the identity column.
Then you re-insert all your data back from temporary holding into the main table (without inserting the old identity).
Example...
NB: run each code block one at a time, checking counts along the way, don't run the whole thing -- and I've left the "dangerous" bits commented out just in case
/** select all columns but NOT the id into a temp location (dont use a # table) **/
SELECT col1, col2, col3, col4, col5
INTO tmpTable
FROM Table1
/** before truncation, double check counts in both match!! **/
-- SELECT COUNT(2) FROM tmpTable
-- SELECT COUNT(2) from Table1
-- TRUNCATE TABLE Table1
INSERT INTO Table1
SELECT col1, col2, col3, col4, col5
FROM tmpTable
/** before you drop temp table, make sure Table1 is ok! **/
-- SELECT COUNT(2) FROM tmpTable
-- SELECT COUNT(2) from Table1
-- DROP TABLE tmpTable
Here is a quick test to demonstrate -- I insert 8 rows, delete one, and re-insert. They are correctly re-numbered.
IF OBJECT_ID('DBO.TEST') IS NOT NULL DROP TABLE TEST
IF OBJECT_ID('DBO.TMP') IS NOT NULL DROP TABLE TMP
CREATE TABLE TEST ([ID] INT IDENTITY(1,1), [SOMESTRING] NVARCHAR(50))
INSERT INTO TEST([SOMESTRING])
SELECT 'HI' UNION
SELECT 'THESE' UNION
SELECT 'ARE' UNION
SELECT 'SOME' UNION
SELECT 'STRINGS' UNION
SELECT 'JUST' UNION
SELECT 'TO' UNION
SELECT 'DEOMONSTRATE'
SELECT *
FROM TEST
DELETE FROM TEST
WHERE SOMESTRING='SOME'
SELECT SOMESTRING
INTO TMP
FROM TEST
TRUNCATE TABLE TEST
INSERT INTO TEST
SELECT SOMESTRING
FROM TMP
SELECT * FROM TEST

It seems SELECT MAX([ColumnName]) returns value from deleted records if [ColumnName] is auto increment int type

In SQL Server or maybe other databases, if a column is auto increment int type, the table can remember the highest value even if the record has been deleted.Let's say you have a table whose with some records previously deleted, and then you use SELECT MAX([ColumnName]), it might return a value associated with a deleted record. Has anyone seen scenarios like this?
This will not happen with SELECT MAX (as can be seen from the below script) in Sql Server.
CREATE TABLE TEST_TABLE (
ID INT IDENTITY (1,1),
Val INT
)
INSERT INTO TEST_TABLE (Val) SELECT 1
INSERT INTO TEST_TABLE (Val) SELECT 2
INSERT INTO TEST_TABLE (Val) SELECT 3
INSERT INTO TEST_TABLE (Val) SELECT 4
INSERT INTO TEST_TABLE (Val) SELECT 5
DELETE FROM TEST_TABLE WHERE Val >= 3
SELECT MAX(ID) MaxID
FROM TEST_TABLE
DROP TABLE TEST_TABLE
Output
MaxID
2
If you were looking for the Tables Identity Value, see #AdaTheDev answer.
Yes, that's by design. Used IDENTITY values are not re-assigned when a record is deleted.
To get the last identity value assigned, you'd need to use IDENT_CURRENT, which (quote)
Returns the last identity value generated for a specified table or view. The last identity value generated can be for any session and any scope.
e.g.
SELECT IDENT_CURRENT('TableName')
I'd say that if you're taking the MAX() on an identity/auto-increment column, then you're doing something wrong.
As #astander says, it's not behaviour I've observed under SQL Server.
You should treat such identifiers as opaque - that they happen to be structured as an integer is a mere convenience to you, with well known storage requirements, clustering behaviours, etc.
It is dev (not sysadmin's or DBA's) board - don't do this in production!
To check what is the next ID:
DBCC CHECKIDENT ('YourTableName', NORESEED)
Note that your next ID will be #MaxID+1:
DECLARE #MaxID INT;
SELECT #MaxID = COUNT(ID) FROM YourTableName;
DBCC CHECKIDENT('YourTableName', RESEED, #MaxID);

how to change identity increment of column

Following statement can reset seed
DBCC CHECKIDENT ('TableName', RESEED, 1)
but this time I have to change its increment .
Or you can use Sql Server Management Studio:
Using this approach will most likely recreate the table.
Hope this helps
ALTER TABLE MyCustomers
ALTER COLUMN CustId IDENTITY (200, 2)
Code from ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/ssmprog3/html/5719d3e4-14db-4073-bed7-d08f39416a39.htm
We can't update a column's identity to increment by 2 on each entry. The easiest method is to create another table with IDENTITY(1,2) and move the data to that table before dropping the actual table. Please go through the script below.
Let TableA is our actual table.
CREATE TABLE TableB(col1 INT IDENTITY (1,2) NOT NULL, col2 VARCHAR(10) NULL);
INSERT INTO TableB SELECT col2 FROM TableA;
DROP TABLE TableA;
sp_rename TableB, TableA;
You can reset the auto increment to a higher value by
Set IDENTITY_INSERT off
Running an insert statement with ID set to where you want to continue from
Set IDENTITY_INSERT on
Delete the row created (assuming it was only done to increment seed)
For example;
Table 'People' with last ID = 10 can be set to continue from 400,000 by;
SET IDENTITY_INSERT AccessToken off
insert into People(Id, name) values (400000,'Bob')
SET IDENTITY_INSERT AccessToken on
Delete from People where ID = 400000