Yes i am very well aware the consequences. But i just want to reorder them. Start from 1 to end.
How do I go about reordering the keys using a single query ?
It is clustered primary key index
Reordering like
First record Id 1
second record Id 2
The primary key is Int
- Drop PK constraint
- Drop Identity column
- Re-create Identity Column
- Re-Create PK
USE Test
go
if(object_id('IdentityTest') Is not null)
drop table IdentityTest
create table IdentityTest
(
Id int identity not null,
Name varchar(5),
constraint pk primary key (Id)
)
set identity_insert dbo.IdentityTest ON
insert into dbo.IdentityTest (Id,Name) Values(23,'A'),(26,'B'),(34,'C'),(35,'D'),(40,'E')
set identity_insert dbo.IdentityTest OFF
select * from IdentityTest
------------------1. Drop PK constraint ------------------------------------
ALTER TABLE [dbo].[IdentityTest] DROP CONSTRAINT [pk]
GO
------------------2. Drop Identity column -----------------------------------
ALTER table dbo.IdentityTest
drop column Id
------------------3. Re-create Identity Column -----------------------------------
ALTER table dbo.IdentityTest
add Id int identity(1,1)
-------------------4. Re-Create PK-----------------------
ALTER TABLE [dbo].[IdentityTest] ADD CONSTRAINT [pk] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
--------------------------------------------------------------
insert into dbo.IdentityTest (Name) Values('F')
select * from IdentityTest
IDENTITY
columns are not updatable irrespective of SET IDENTITY_INSERT
options.
You could create a shadow table with the same definition as the original except for the IDENTITY
property. Switch into that (this is a metadata only change with no movement of rows that just affects the table's definition) then update the rows and switch back though.
A full worked example going from a situation with gaps to no gaps is shown below (error handling and transactions are omitted below for brevity).
Demo Scenario
/*Your original table*/
CREATE TABLE YourTable
(
Id INT IDENTITY PRIMARY KEY,
OtherColumns CHAR(100) NULL
)
/*Some dummy data*/
INSERT INTO YourTable (OtherColumns) VALUES ('A'),('B'),('C')
/*Delete a row leaving a gap*/
DELETE FROM YourTable WHERE Id =2
/*Verify there is a gap*/
SELECT *
FROM YourTable
Remove Gaps
/*Create table with same definition as original but no `IDENTITY`*/
CREATE TABLE ShadowTable
(
Id INT PRIMARY KEY,
OtherColumns CHAR(100)
)
/*1st metadata switch*/
ALTER TABLE YourTable SWITCH TO ShadowTable;
/*Do the update*/
WITH CTE AS
(
SELECT *,
ROW_NUMBER() OVER (ORDER BY Id) AS RN
FROM ShadowTable
)
UPDATE CTE SET Id = RN
/*Metadata switch back to restore IDENTITY property*/
ALTER TABLE ShadowTable SWITCH TO YourTable;
/*Remove unneeded table*/
DROP TABLE ShadowTable;
/*No Gaps*/
SELECT *
FROM YourTable
I don't think there is any way to do this in a single query. Your best bet is to copy the data to a new table, drop and recreate the original table (or delete the data and reseed the identity) and reinsert the data in the original order using the previous identity as the ordering (but not re-inserting it).
CREATE TABLE Table1_Stg (bla bla bla)
INSERT INTO Table1_Stg (Column2, Column3,...) SELECT Column2, Column3,... FROM Table1 ORDER BY Id
Here the Id column is excluded from the SELECT column list.
Or, you can do:
SELECT * INTO Table1_Stg FROM Table1 ORDER BY Id
DROP Table1
sp_rename Table1_stg Table1
Please lookup the usage for sp_rename as I am doing this from memory.
Hope this helps.
EDIT: Please save a script with all your indexes and constraints if any on Table1.
EDIT2: Added second method of creating table and inserting into table.
UPDATE tbl SET id = (SELECT COUNT(*) FROM tbl t WHERE t.id <= tbl.id);