How do I get first unused ID in the table?

后端 未结 6 1966
温柔的废话
温柔的废话 2021-01-12 23:58

I have to write a query wherein i need to allocate a ID (unique key) for a particular record which is not being used / is not being generated / does not exist i

6条回答
  •  佛祖请我去吃肉
    2021-01-13 00:42

    /*
    This is a query script I wrote to illustrate my method, and it was created to solve a Real World problem where we have multiple machines at multiple stores creating transfer transactions in their own databases,
    that are then synced to other databases on the store (this happens often, so getting the Nth free entry for the Nth machine should work) where the transferid is the PK and then those are synced daily to a MainFrame where the maximum size of the key (which is the TransactionID and StoreID) is limited.  
    */
    
    --- table variable declarations
    /* list of used transaction ids (this is just for testing, it will be the view or table you are reading the transaction ids from when implemented)*/
    
    DECLARE @SampleTransferIDSourceTable TABLE(TransferID INT)     
    
    /* Here we insert the used transaction numbers*/
    
    DECLARE @WorkTable TABLE (WorkTableID INT IDENTITY (1,1), TransferID INT) 
    
    /*this is the same table as above with an extra column to help us identify the blocks of unused row numbers (modifying a table variable is not a good idea)*/
    
    DECLARE @WorkTable2 TABLE (WorkTableID INT , TransferID INT, diff int)  
    
    --- Machine ID declared
    
    DECLARE @MachineID INT
    
    -- MachineID set
    
    SET @MachineID = 5
    
    -- put in some rows with different sized blocks of missing rows.
    -- comment out the inserts after two to the bottom to see how it handles no gaps or make 
    -- the @MachineID very large to do the same.
    -- comment out early rows to test how it handles starting gaps.
    
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 1 )
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 2 )
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 4 )
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 5 )
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 6 )
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 9 )
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 10 )
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 20 )
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 21 )
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 24 )
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 25 )
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 30 )
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 31 )
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 33 )
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 39 )
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 40 )
    INSERT @SampleTransferIDSourceTable ( TransferID ) VALUES ( 50 )
    
    -- copy the transaction ids into a table with an identiy item.
    -- When implemented add where clause before the order by to limit to the local StoreID
    -- Zero row added so that it will find gaps before the lowest used row.
    
    INSERT @WorkTable (TransferID)
    
    SELECT 0
    
    INSERT @WorkTable (TransferID)
    
    SELECT TransferID FROM @SampleTransferIDSourceTable ORDER BY TransferID   
    
    -- copy that table to the new table with the diff column 
    
    INSERT @WorkTable2
    
    SELECT WorkTableID,TransferID,TransferID - WorkTableID 
    
      FROM @WorkTable              
    
    --- gives us the (MachineID)th unused ID or the (MachineID)th id beyond the highest id used.
    
    IF EXISTS (
    
    SELECT Top 1
    
           GapStart.TransferID  + @MachineID - (GapStart.diff + 1)
    
      FROM @WorkTable2 GapStart
    
     INNER JOIN @WorkTable2 GapEnd
    
        ON GapStart.WorkTableID = GapEnd.WorkTableID - 1
    
       AND GapStart.diff < GapEnd.diff
    
       AND gapEnd.diff >= (@MachineID - 1)
    
     ORDER BY GapStart.TransferID
    
     )
    
    SELECT Top 1
    
           GapStart.TransferID  + @MachineID - (GapStart.diff + 1)
    
      FROM @WorkTable2 GapStart
    
     INNER JOIN @WorkTable2 GapEnd
    
        ON GapStart.WorkTableID = GapEnd.WorkTableID - 1
    
       AND GapStart.diff < GapEnd.diff
    
       AND gapEnd.diff >= (@MachineID - 1)
    
     ORDER BY GapStart.TransferID
    
    ELSE 
    
    SELECT MAX(TransferID) + @MachineID FROM @SampleTransferIDSourceTable
    

提交回复
热议问题