SQL Server: Working with Identity Column After Table Creation
Introduction
MS SQL Server uses the IDENTITY keyword to perform an auto-increment feature. It allows a unique number to be generated when a new record is inserted into a table. It is used with the syntax:
CREATE TABLE City
(
ID int IDENTITY(1,1) PRIMARY KEY,
Name varchar(50)
)
However, once the table has been created, we cannot use the Alter command to add an Identity to the table. Using Alter Command to add Identity will throw an exception. If we go to the design of the table, we can see a property named ‘Identity Specification’ that can be set to enable identity.
Even in the design mode, it will be disabled/grayed out. This is the case if we have a Primary Key set on the column that we are trying to add an Identity.
Set Identity to Non-Primary Field
However, if the column ‘Id’ was not set as the Primary Key, we can set the Identity from the Design mode as shown below:
In the upcoming section, we will see various options to add Identity to an existing table.
Add an Identity Column
One option to add an Identity to the table is to add a new column to the table and set it as identity. This is possible through the Alter statement. However, if we want to set the Identity to an already existing column in the table we cannot use this DDL command.
Alter Table City Add CityId int Identity(1,1)
Moreover, if we try to add an additional Identity column to an already created table using the below Alter command, it will throw the exception as only one identity column can be specified for a table.
Alter Table City Add NewIdentity int Identity(1,1)
Create a new Identity Column and Rename it to dropped Column(With Data Loss)
Another option if we want the identity column to be applied to an existing column name is:
- Add a new column and set it as Identity
- Remove the old column
- Rename the new column to the old column name
This way we get the feeling that the identity has been applied to the existing column in the table.
Alter Table City
Add CityId Int Identity(1, 1)
Go
Alter Table City Drop Column Id
Go
Exec sp_rename 'City.CityId', 'Id', 'Column'
Prior to running the script the table values for the Id column was:
After running the script we can see that the Id column has been overwritten with new Identity values causing data loss in the column.
Create an Identity Column by re-creating the Table without any data loss
One viable option to prevent the data loss associated with the previous approach is to recreate the table with the Identity column and load the data into it. The steps followed in this approach is:
- Create a temporary table with the Identity Column
- Copy the data from the original table into the temporary table
- Drop the original table
- Rename the temporary table to the original table name
CREATE TABLE dbo.Tmp_City
(
Id int NOT NULL IDENTITY(1, 1),
Name varchar(50) NULL,
Country varchar(50) ,
)
ON [PRIMARY]
go
SET IDENTITY_INSERT dbo.Tmp_City ON
go
IF EXISTS ( SELECT *
FROM dbo.City )
INSERT INTO dbo.Tmp_City ( Id, Name,Country )
SELECT Id,
Name,Country
FROM dbo.City TABLOCKX
go
SET IDENTITY_INSERT dbo.Tmp_City OFF
go
DROP TABLE dbo.City
go
Exec sp_rename 'Tmp_City', 'City'
This way we the identity will be set to the column, as well as the data, will be preserved.
Use Generate Scripts Option
The above approach can be automated by generating the script that will create the table along with the data. In this approach, we will use the Generate scripts option available at the DB Level. The steps are:
- Get the script to create the table along with the data using the ‘Generate Scripts’ option
- Add Identity to the generated script
- Drop the existing table and run the generated script
Upon right-clicking DB , Select Tasks -> Generate Scripts
This will open up the Generate and Publish Scripts window.
Select the table for whom we want to generate the script.
Select Save to file radio button and click Advanced.
Change Type of data to script from ‘Schema’ to ‘Schema and data’.
Proceed to the next page.
This will complete the generation of the script.
Going ahead to the script location we had specified, we can see the table creation script along with the data to be inserted. We can now add the Identity Keyword to the script and run it after dropping the existing table.
However, when there are gigs of data above approaches of recreating the table and re-inserting the data is not efficient. We will see how to overcome that in the final approach discussed in this article
Recreate the table with Identity and use Partition Switching
Above methods can be quite a time consuming if there are millions of records present in the table. To speed up the data population after table creation with Identity specification we can transfer the data using partition switching. The steps followed in this process are:
- Create the table with the same schema as the original table and include Identity column
- Use Switch to transfer the partition from old table to new table
- Drop the old table
- Rename the new table to old table
This is much faster than inserting all the records back to the new table as Insert is an expensive operation. Partition Switching on the other hand does only meta data updates to the location of the existing data and no data is moved or duplicated making it faster and efficient.
CREATE TABLE dbo.Tmp_City
(
Id int NOT NULL IDENTITY(1, 1),
Name varchar(50) NULL,
Country varchar(50) ,
)
ON [PRIMARY]
go
SET IDENTITY_INSERT dbo.Tmp_City ON
go
Alter Table City switch to Tmp_City;
go
DROP TABLE dbo.City
go
Exec sp_rename 'Tmp_City', 'City'
Summary
Identity Column is a great way to enable auto increment in the table. But we will have to keep in mind the below points failing which we will end up using one of the above methods to add Identity to the table.
- Always make design consideration while choosing Identity for a table as adding it post creation of the table becomes a tedious task when there are millions of records present in the table.
- Try not to set the Identity column as the Primary key. The Primary Key constraint will prevent users from adding an Identity to that column from the Design Page after the table creation.
Reference
Multiple resources had been referred to sum up the various options that can be utilized to circumvent the Identity assignment issue. Few of the Forums and Articles that helped are linked below: