I have a table with a primary key field ID. I don't want to use Identity because i need to give the User the posibility of manualy choose an ID for the new object. So my idea is:
The question is how to query and SQL Server table to get the firts free ID number?
Examples 1:
ID
--
1
2
10
First free ID is 3
Examples 2:
ID
--
1
2
3
4
First free ID is 5
Is there a way to do that? All i can think of is get the min and max value, create a cycle for possible values and then compare with table data, but it involves too many querys to the database. Thanks!
You can find the first free id as the first id where there is no "next" value:
select coalesce(min(t.id) + 1, 0)
from table t left outer join
     table t2
     on t.id = t2.id - 1
where t2.id is null;
EDIT:
If you want to handle "1" as a potential missing value:
select (case when min(minid) > 1 then 1 else coalesce(min(t.id) + 1, 0) end)
from table t left outer join
     table t2
     on t.id = t2.id - 1 cross join
     (select min(id) as minid from table t) const
where t2.id is null;
Test Table
CREATE TABLE ID_TABLE(ID INT)
INSERT INTO ID_TABLE VALUES
(1),(2),(10)
Stored Procedure
ALTER PROCEDURE dbo.usp_GetNextValue
@nxt_ID_Wanted INT = 0,
@nxt_ID_Available INT  OUTPUT
AS
BEGIN
  SET NOCOUNT ON;
  -- If user hasnt passed any value get next avilable value
IF (@nxt_ID_Wanted = 0)   
 BEGIN 
          SELECT TOP 1 @nxt_ID_Available  =  ID + 1 
        FROM 
         (
          SELECT   ID , ROW_NUMBER() OVER (ORDER BY ID ASC) AS rn
         FROM ID_TABLE
         )Q
        WHERE ID = rn
        ORDER BY ID DESC
      IF (@nxt_ID_Available IS NULL)
        BEGIN
          SET @nxt_ID_Available = 1;
        END
 END
     -- If user has passed a value check if it exists and raise error
ELSE  IF EXISTS(SELECT 1 FROM ID_TABLE WHERE ID = @nxt_ID_Wanted)
 BEGIN
       RAISERROR('Selected ID value already exists',16,1)
       SET @nxt_ID_Wanted = 0;
       RETURN;
 END 
ELSE      -- else just let the user have the value he/she wanted
 BEGIN 
   SET @nxt_ID_Available = @nxt_ID_Wanted;
 END
END
Execute Procedure
DECLARE @ID INT;
EXECUTE dbo.usp_GetNextValue @nxt_ID_Wanted = 6
                             ,@nxt_ID_Available = @ID OUTPUT
SELECT @ID
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With