开发者

SQL Server find first gap between ID key fields

开发者 https://www.devze.com 2023-04-04 22:23 出处:网络
Is there any other better way to perform this operation? -- USE EXAMPLE: EXEC GetFirstIdInGap @tableName =\'Employees\',@column=\'IdEmployee\'

Is there any other better way to perform this operation?

-- USE EXAMPLE: EXEC GetFirstIdInGap @tableName ='Employees',@column='IdEmployee'
CREATE PROCEDURE GetFirstIdInGap 
    (@tableName sysname, 
    @column sysname)
AS
    IF @tableName IS NOT NULL and @column IS NOT NULL
    BEGIN
        DECLARE @col varchar(50), @col2 varchar(50)
        SET @col = 'A.' + @column;
        SET @col2 = 'A2.' + @column;
        EXEC ('SELECT ISNULL((MIN('+@col+') - 1),(SELECT ISNULL(MAX('+@column+')+1,1) FROM '+@tableName+')) 
                    AS '+@column+'
                    FROM '+@tableName+' AS a
                    LEFT JOIN '+@tableName+' AS a2
                            ON '+@col2+' = '+@col+' - 1
                    WHERE '+@col2+' IS NULL AND '+@col+' > 1');
    END
GO

It gets the first free ID (if there are gaps) or the last one + 1 given a @tableName and @column. If there are no rows, it returns as the first ID 开发者_JAVA百科= 1.

UPDATE:

For those who have asked about why do I need gaps of ID's, I am gonna explain my problem (although I didn't want to dig into it). I work with C# Winforms applications against other firmware applications which have serious memory restrictions. One of those restrictions is that I can only use a maximum code value of 65536. Those codes are equivalent of database ID's, and in some cases the firmware code had reached the value of 65536. That's why gap reusing would be wonderful for me.


t is your table

select 
coalesce((select min(id)+1 from t mt where not exists(select 1 from t where id+1 = mt.id )), 1) firstgap


Here is an approach that doesn't require a numbers table (even one with more than 1,000 rows):

CREATE PROCEDURE dbo.GetFirstIdInGap_2
    @table  SYSNAME,
    @column SYSNAME
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @sql NVARCHAR(MAX) = N';WITH c AS
        (
            SELECT n = ' + @column + ', 
              rn = ROW_NUMBER() OVER (ORDER BY ' + @column + ')
            FROM ' + @table + '
        )
        SELECT ' + @column + ' = 1 + COALESCE(
            (SELECT MIN(c.n) FROM c INNER JOIN c AS n
            ON n.rn = c.rn + 1 WHERE n.n - c.n > 1),
            (SELECT MAX(c.n) FROM c),
            0);';

    EXEC sp_executesql @sql;
END
GO


t is your table

select  min(isnull(id,0)+1) from t where  isnull(id,0) + 1 not in (select isnull(id,0) from t)
0

精彩评论

暂无评论...
验证码 换一张
取 消