Today I created a random ID. The random ID must still be primary key what means that it must be unique. This is a code walk-through to solve this problem:
First of all I created a play-ground to make tests (with 4 test-entries).
First of all I created a play-ground to make tests (with 4 test-entries).
declare @tbl TABLE(ID int)
insert into @tbl values (3), (7), (9), (10)
Then I introduced a parameter to define the scope. Here we see 0 as an error case (no more IDs available) and start with ID 1 to @maxValue.
declare @maxValue int = 10Then we create a loop to test the development for example 20 times:
declare @i int = 0
while (@i < 20) begin
The idea now is to create a random value (=myRequestID) and to check whether the ID currently in use (if so, it will be copied to targetID).
declare @myRequestID int = (cast( (RAND()*(@maxValue-1)) as int) + 1)if we have already used this value (it exists in @tbl) then we need to search for an ID after the random value. Therefore we can choose all requested entries after the random value which have no next sibling and return the smallest id + 1
declare @myTargetID int = 0
if not exists(select * from @tbl where ID = @myRequestID) begin
set @myTargetID = @myRequestID
insert into @tbl values (@myTargetID)
end else begin
select @myTargetID = isnull(MIN(id) + 1, 0) from @tbl t
where id between @myRequestID and (@maxValue - 1)
and not exists(select * from @tbl innerT where innerT.ID = t.ID + 1)
if the targetID has a value we found a valid entry, else if the value is zero, we have not found an entry after the random value, so we jump over the maxValue border and restart at the beginning. Here we need to consider that the value 1 is a special case which needs to be handled extraordinary.
if @myTargetID <> 0 begin
insert into @tbl values (@myTargetID)
end else if not exists(select * from @tbl where ID = 1) begin
set @myTargetID = 1;
insert into @tbl values (@myTargetID)
Finally if 1 is already in use we can search for an ID hole from the start to the random value
end else begin
select @myTargetID = isnull(MIN(id) + 1, 0) from @tbl t
where id < @myRequestID
and not exists(select * from @tbl innerT where innerT.ID = t.ID + 1)
if @myTargetID <> 0 begin
insert into @tbl values (@myTargetID)
end
end
If no value was found in the end there is probably no hole available and we have no value to return.
if @myTargetID = 0 begin(end of the loop)
print 'no value'
end
end
set @i = @i + 1;
end
kr, Daniel
No comments:
Post a Comment