A couple of month ago, I migrated one of my client’s data from SQL Server earlier versions to SQL Server 2012. The most important part was, I changed all the identity columns of the tables from identity to sequence in the entire database, here is the solution. But another important aspect that I did not discuss is that, whenever you migrate or create a new sequence column make sure that it is not be changeable like identity columns. In the identity column it is implemented by default but in sequence column, you must implement it. But how ?
First of all let me update an identity column of a table to show how identity columns are prevented from being changed (by default). Given below is the script.
--This script is compatible with SQL Server 2005 and above. USE AdventureWorks2012 GO UPDATE HumanResources.Department SET [DepartmentID]=17 WHERE [DepartmentID]=16 --OUTPUT
Msg 8102, Level 16, State 1, Line 1
Cannot update identity column ‘DepartmentID’.
Solution :
By default, sequence columns are not prevented from being changed, you need to manually control this aspect. Let me show you the solution step by step.
Step 1 :
Let me create a table to demonstrate the solution.
USE tempdb GO --DROP TABLE tbl_sample_Seq --GO CREATE TABLE tbl_sample_Seq ( [ID] int, [Name] varchar(50) ) GO
Step 2 :
Once you created the table, create a sequence object to insert [ID]s in the table.
USE tempdb GO --DROP SEQUENCE [dbo].[Seq_Student] --GO CREATE SEQUENCE [dbo].[Seq_Student] AS [int] START WITH 1 INCREMENT BY 1 MINVALUE 1 MAXVALUE 1000 GO
Step 3 :
Once you created the sequence object, insert few records using sequence object in the table. Given below is the script.
USE tempdb GO INSERT INTO tbl_sample_Seq VALUES (NEXT VALUE FOR [Seq_Student],'Imran') INSERT INTO tbl_sample_Seq VALUES (NEXT VALUE FOR [Seq_Student],'Bob') INSERT INTO tbl_sample_Seq VALUES (NEXT VALUE FOR [Seq_Student],'Alexander') INSERT INTO tbl_sample_Seq VALUES (NEXT VALUE FOR [Seq_Student],'Hosanna') INSERT INTO tbl_sample_Seq VALUES (NEXT VALUE FOR [Seq_Student],'William') GO
Step 4 :
Let me browse the table and show the records that have been inserted successfully.
USE tempdb GO SELECT * FROM tbl_sample_Seq GO --OUTPUT
Step 5 :
Lets update the sequence column. Do not DO this step in your production database. This step is just to demonstrate the issue.
USE tempdb GO UPDATE tbl_sample_Seq SET [ID]=33 WHERE [ID]=3 GO --OUTPUT
(1 row(s) affected)
Step 6 :
Ooops….in the above step the [ID] column of the table got modified. Let me create an update trigger on the [ID] column of the table, so that we can prevent sequence values from being changed. This is the most important step while implementing sequence object in a table. Do not skip it.
USE tempdb GO CREATE TRIGGER trg_update ON tbl_sample_Seq AFTER UPDATE AS BEGIN SET NOCOUNT ON; DECLARE @OldID int DECLARE @NewID int SELECT @OldID =[ID] FROM deleted SELECT @NewID =[ID] FROM inserted --Print @OldID --Print @NewID IF @OldID <> @NewID BEGIN RAISERROR('Failed', 16, 1); ROLLBACK TRANSACTION END END GO
Step 7 :
Once the update trigger has been created, lets update the sequence column ([ID]) again.
USE tempdb GO UPDATE tbl_sample_Seq SET [ID]=33 WHERE [ID]=3 GO --OUTPUT
Msg 50000, Level 16, State 1, Procedure trg_update, Line 19
Failed
Msg 3609, Level 16, State 1, Line 1
The transaction ended in the trigger. The batch has been aborted.
Conclusion :
Whenever you implement sequence object in any table, make sure you create the trigger to prevent sequence values from being changed.
Let me know if you came across this issue and its solutions.
Leave a Reply