Inserting rows with sequential identity using Triggers - sql-server

I'm trying to overcome the problem of identity gaps in my table that occur when i delete rows, where the SQL Server management studio increments not the last identity that exists in the table but the last created row identity even if it was deleted.
I'm not sure how to do this in a trigger:
1- When a row is being inserted
2- Get the last identity that exists in the table
3- Increment that identity by 1
4- Set the identity of the row being inserted to the new identity in (3-)
5- Perform the insert

You can use DBCC CHECKIDENT to reset the identity to max identity value in the table
Checks the current identity value for the specified table
and, if it is needed, changes the identity value. You can
also use DBCC CHECKIDENT to manually set a new current identity value
for the identity column.
Simple Demo
CREATE TABLE trgtest
(
id INT IDENTITY(1, 1),
NAME VARCHAR(30)
)
INSERT INTO trgtest
VALUES ('A'),('B'),('C'),('D')
SELECT * FROM trgtest
DELETE FROM trgtest
WHERE NAME = 'D'
DECLARE #max_id INT
SELECT #max_id = Max(id)
FROM trgtest
DBCC checkident(trgtest, reseed, #max_id) -- Reseting the Identity value to Max identity value in Table
INSERT INTO trgtest
VALUES ('D')
SELECT * FROM trgtest

Related

SQL Server creating a Table with an IDENTITY COLUMN - uniqueness

In SQL Server, I have created a Table with an ID column that I have made an IDENTITY COLUMN,
EmployeeID int NOT NULL IDENTITY(100,10) PRIMARY KEY
It is my understanding, when I use the IDENTITY feature, it auto increments the EmployeeID. What I don't know/not sure is:
Is that IDENTITY number created, unique?
Does SQL search the entire column in the table to confirm the number created does not already exist?
Can I override that auto increment number manually?
If I did manually override that number, would the number I enter be checked to make sure it is not a duplicate/existing ID number?
Thanks for any help provided.
Is that IDENTITY number created, unique?
Yes, Identity property is unique
Does SQL search the entire column in the table to confirm the number created does not already exist? \
It need not, what this property does is, just incrementing the old value
Can I override that auto increment number manually?
Yes, you can. You have to use SET IDENTITY_INSERT TABLENAME ON
If I did manually override that number, would the number I enter be checked to make sure it is not a duplicate/existing ID number?
No, that won't be taken care by SQL Server, you will have to ensure you have constraints to take care of this
Below is a simple demo to prove that
create table #temp
(
id int identity(1,1)
)
insert into #temp
default values
go 3
select * from #temp--now id column has 3
set identity_insert #temp on
insert into #temp (id)
values(4)
set identity_insert #temp off
select * from #temp--now id column has 4
insert into #temp
default values
go
select * from #temp--now id column has 5,next value from the last highest
Updating info from comments:
Identity column will allow gaps once you reseed them,also you can't update them

alter a table column and set identity from max existing in that column in sql server 2008

I have a Column with MaxCode name, in Mytable that filled before,now i want alter this column and set it type to identity that start with max number existing in column MaxCode
Use below code to reset seed value for Identity column
DECLARE #newSeed NUMERIC(10)
SELECT #newSeed = MAX(MaxCode) FROM Mytable
DBCC CHECKIDENT (Mytable, RESEED, #newSeed)

Alter column to be identity

I've already read the following answers about the impossibility to alter a column into identity once has been created as a regular int.
Adding an identity to an existing column
How to Alter a table for Identity Specification is identity SQL Server
How to alter column to identity(1,1)
But the thing is I have a table which has been migrated to a new one where the ID was not declared as identity from the beginning, because the old table which was created with an ID identity a long time ago has missing rows due to a purge of historical data. So as far as I know, if I add a new column as identity on my new table, it will automatically create the column sequentially and I need to preserve the IDs from the old table as-is because there is already data linked to these previous IDs.
How can I do transform my ID column from the new table as identity but not sequentially, but with the IDs from the old table?
You could try this approach:
Insert rows with old ID with SET IDENTITY_INSERT <new table> ON. This allows you to insert your own ID.
Reseed the Identity, setting it to the highest ID value +1 with DBCC CHECKIDENT ('<new table>', RESEED, <max ID + 1>). This will allow your Identity to increase from the highest ID and forward.
Something like this in code:
-- Disable auto increment
SET IDENTITY_INSERT <new table> ON
-- <INSERT STUFF HERE>
SET IDENTITY_INSERT <new table> OFF
-- Reseed Identity from max ID
DECLARE #maxval Int
SET #maxval = ISNULL(
(
SELECT
MAX(<identity column>) + 1
FROM <new table>
), 0)
DBCC CHECKIDENT ('<new table>', RESEED, #maxval)
EDIT: This approach requires your ID-column to be an Identity, of course.
If you don't have nulls in the field that you want to copy over from your previous version, you could first figure out what the largest ID is by just doing a max(Id) select. Then using SSMS go add your new field and when you set it as identity, just set the SEED value to something higher than what your current max is so you don't have collisions on new inserts.
I have a process where a temp table is used between a source file, CSV and the production table. The temp table has to match the CSV file columns, there is no PK in this data.
To find a set of rows before and after where the Azure Data Factory was failing, I imported over 2,000,000 rows into a temp table. The process stopped in Azure at 1,500,000 rows.
The error was that an integer or string would be truncated.
This line of code added a PK to the temp table and incremented it:
ALTER TABLE ##FLATFILETEMPBDI ADD ROWNUM INT IDENTITY
That would be the simplest solution to get a row number. I was then able to do this query to find the rows just before and after 1,500,000:
SELECT
ROWNUM
, PARTDESCRIPTION
, LEN(PARTDESCRIPTION) AS LENDESCR
, QUANTITY
, ONORDER
, PRICE
, MANUFACTURERPARTNUMBER
FROM ##FLATFILETEMPBDI
WHERE ROWNUM BETWEEN 1499990 AND 1500005
Works perfectly -- was not planning on it to be that easy, was surprised as anyone to see that the ALTER TABLE with IDENTITY worked to do the numbering for me.

is it possible that an auto increment field duplicates?

I have a table which has several field including:
contact_id
phone
phone_id
contact_id and phone are primary keys and phone_id is an auto increment field. I want to use it to recognize a certain entry. So I want to know that is it possible to duplicate that non primary field when I'm entering data.
Unless there is no constraint, some unique index, you can duplicate values in that column, because 1) you can turn identity_insert on, 2) you can reseed increments.
Here is a proof:
CREATE TABLE #test(id INT IDENTITY(1, 1))
INSERT INTO #test DEFAULT VALUES
INSERT INTO #test DEFAULT VALUES
INSERT INTO #test DEFAULT VALUES
SET IDENTITY_INSERT #test ON
INSERT INTO #test(id) VALUES(1)
SET IDENTITY_INSERT #test OFF
INSERT INTO #test DEFAULT VALUES
INSERT INTO #test DEFAULT VALUES
DBCC CHECKIDENT ('#test', RESEED, 1);
INSERT INTO #test DEFAULT VALUES
INSERT INTO #test DEFAULT VALUES
SELECT * FROM #test
DROP TABLE #test
Output:
id
1
2
3
1
4
5
2
3
The short answer is Yes, it's possible.
SQL Server does not force a unique constraint on identity columns, meaning that the can have duplicated values, however, Sql server will not generate duplicate values itself in an identity column.
Identity columns in sql server are populated by the sql server itself when you insert a row to the table.
However, you can specify a value to them by using SET IDENTITY_INSERT before the insert statement.
There are a couple of things that you should be aware of:
Setting identity_insert on is per table. you can only set it for one table at the time.
Until you set the identity_insert back off, any insert statement to that table will have to specify a value for the identity column.
you can't use set identity insert on for more then one table on a single session. therefor after you've done inserting records to the table you must set the identity_insert back off on that table.

SQL Server 2008 R2: IDENTITY

Q 1:
I have a empty table to insert records. Having one column of IDENTITY type, for which I want to insert values manually.
Example:
Table: Employee
create table Employee
(
ID int IDENTITY(1,1) PRIMARY KEY,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
Inserting records:
SET IDENTITY_INSERT Employee ON;
insert into Employee values(101,'ABC','XYZ','HighStreet','Moscow')
Error:
Msg 8101, Level 16, State 1, Line 1
An explicit value for the identity column in table 'Employee' can only be specified when a column list is used and IDENTITY_INSERT is ON.
Q 2:
How to get latest inserted ID of an Employee without using MAX and Top?
Answer 1
If you will try to insert the value into Identity column you will get the error
Cannot insert explicit value for identity column in table ‘Employee’
when IDENTITY_INSERT is set to OFF.
Write SET IDENTITY_INSERT table name ON before the insert script and
SET IDENTITY_INSERT table name Off after insert script
SET IDENTITY_INSERT Employee ON
insert into Employee(ID,LastName,FirstName,Address,City) values
(101,'ABC','XYZ','HighStreet','Moscow')
SET IDENTITY_INSERT Employee OFF
Answer 2
There are several ways using like this after insert statement
After an INSERT, SELECT INTO, or bulk copy statement is completed,
##IDENTITY contains the last identity value that is generated by the
statement
SELECT ##IDENTITY
It returns the last IDENTITY value produced on a connection,
regardless of the table that produced the value, and regardless of the
scope of the statement that produced the value.
SELECT SCOPE_IDENTITY()
It returns the last IDENTITY value produced on a connection and by a
statement in the same scope, regardless of the table that produced the
value.
SELECT IDENT_CURRENT(‘Employee’)
It returns the last IDENTITY value produced in a table, regardless of
the connection that created the value, and regardless of the scope of
the statement that produced the value. IDENT_CURRENT is not limited by
scope and session; it is limited to a specified table. IDENT_CURRENT
returns the identity value generated for a specific table in any
session and any scope.
MSDN SOURCE
You can use IDENT_CURRENT( 'table_name' ) to get the current value.
For external value of Identity column Column Name given explicitly is Must as below
SET IDENTITY_INSERT Employee ON;
insert into Employee(ID ,LastName,FirstName,Address,City)
values(101,'ABC','XYZ','HighStreet','Moscow')

Resources