SQL Developers, did you ever come across a situation where
you need to find missing identity or sequence number for a given table? For
instance, someone deleted few records from a table which has an IDENTITY column.
Have you wondered how to find those missing rows? In this blogpost, I am going
to explain different ways to find missing identity or sequence numbers.
First I will create some sample data for demonstration
purpose.
-- Prepare Test data --SET NOCOUNT ON
IF OBJECT_ID('dbo.TestData') IS NOT NULL DROP TABLE dbo.TestData
CREATE TABLE dbo.TestData (
ID INT IDENTITY(1, 1) NOT NULL)
DECLARE @Counter INT = 1
WHILE @Counter <= 15
BEGIN
INSERT dbo.TestData DEFAULT VALUES
SET @Counter += 1
END
SELECT ID FROM dbo.TestData
-- Now delete some records (IDs)
DELETE dbo.TestData WHERE ID IN (3,7,8,10,12,13)
--Verifiy the data
SELECT ID FROM dbo.TestData
Below are three different ways to identity missing values.
Find
missing sequence numbers using Ranking Function:
-------------------------------------------
-- Option 1: Using Ranking function
-------------------------------------------
DECLARE @MaxID INT = (SELECT MAX(ID) FROM dbo.TestData)
DECLARE @MaxID INT = (SELECT MAX(ID) FROM dbo.TestData)
SELECT SeqID AS MissingSeqID
FROM (SELECT ROW_NUMBER() OVER (ORDER BY column_id) SeqID from sys.columns) LkUp
LEFT JOIN dbo.TestData t ON t.ID = LkUp.SeqID
LEFT JOIN dbo.TestData t ON t.ID = LkUp.SeqID
WHERE t.ID is
null and SeqID < @MaxID
Here
is the output:
-- If there are less records in
sys.columns and
-- you need need larger result then use
CROSS JOIN
SELECT SeqID AS MissingSeqID
FROM (SELECT ROW_NUMBER() OVER (ORDER BY c1.column_id) SeqID
FROM sys.columns c1
CROSS JOIN sys.columns c2) LkUp
LEFT JOIN dbo.TestData t ON t.ID = LkUp.SeqID
WHERE t.ID is
null and SeqID < @MaxID
Find missing sequence numbers using CTE:
-------------------------------------------
-- Option 2: Using Common Table
Expression
-------------------------------------------
DECLARE @MaxID INT = (SELECT MAX(ID) FROM dbo.TestData)
;WITH CTE (MissingSeqID, MaxID)
AS (
SELECT 1 AS MissingSeqID, @MaxID
UNION ALL
SELECT MissingSeqID + 1, MaxID FROM CTE WHERE MissingSeqID < MaxID
)
SELECT MissingSeqID FROM CTE
LEFT JOIN dbo.TestData t on t.ID = CTE.MissingSeqID
WHERE t.ID is
NULL
GO
Find
missing sequence numbers using Tally Table:
This is the most prefered way out of all the above options.
This is the most prefered way out of all the above options.
-------------------------------------------
-- Option 3: Using Tally Table
-------------------------------------------
DECLARE @MaxID INT = (SELECT MAX(ID) FROM dbo.TestData)
SELECT t.ID MissingSeqID FROM dbo.Tally t
LEFT JOIN dbo.TestData td
ON td.ID = t.ID
WHERE td.ID IS NULL
AND t.ID <
@MaxID



Good.......
ReplyDeleteNice post. It really solved my delete logic for implementing CDC in ETL
ReplyDeletegood solution
ReplyDeleteYour blog is nice for more explore this links also.
ReplyDeletefull stack developer course in bangalore
Full Stack Developer Course in Bangalore with Placement