繁体   English   中英

从表中获取第一个未使用的ID?

[英]Getting the first unused Id from a table?

在我们的数据库中,我们有一个缺少标识列的表。 有一个Id列,但在输入记录时会手动填充。 Id超过90,000的所有项目都将保留并在所有客户数据库中全局填充。

我正在构建一个使用Entity Framework处理向此表中批量插入的工具。 我需要找出在没有迭代每一行的情况下即时找到第一个可用ID的最有效方法(小于90,000)。 在许多数据库中,很可能有人只是选择了一个未被使用的随机数,然后使用它来插入行。

我最好的办法是什么?


编辑

在看到列出的一些解决方案之后,我尝试在Linq中复制SQL逻辑。 我怀疑它是完美的,但它似乎是快速和高效的。

var availableIds = Enumerable.Range(1, 89999)
                       .Except(db.Table.Where(n => n.Id <= 89999)
                           .Select(n => n.TagAssociationTypeID))
                       .ToList();

您是否考虑过类似的东西:

SELECT
    min(RN) AS FirstAvailableID
FROM (
    SELECT
        row_number() OVER (ORDER BY Id) AS RN,
        Id
    FROM
        YourTable
    ) x
WHERE
    RN <> Id

要回答有关如何获取可用数字列表的隐式问题:轻松,列出所有可能的数字,然后删除正在使用的数字。

--This builds a list of numbers from 1 to 89999
SELECT TOP (89999) n = CONVERT(INT, ROW_NUMBER() OVER (ORDER BY s1.[object_id]))
INTO #AvialableNumbers
FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
OPTION (MAXDOP 1);

CREATE UNIQUE CLUSTERED INDEX n ON #AvialableNumbers(n)

--Start a seralizeable transaction so we can be sure no one uses a number
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
begin transaction

--Remove numbers that are in use.
delete #AvialableNumbers where n in (select Id from YourTable)

/*
Do your insert here using numbers from #AvialableNumbers
*/    

commit transaction

这是您通过实体框架执行的操作

using(var context = new YourContext(connectionString))
using(var transaction = context.Database.BeginTransaction(IsolationLevel.Serializable))
{
    var query = @"
SELECT TOP (89999) n = CONVERT(INT, ROW_NUMBER() OVER (ORDER BY s1.[object_id]))
INTO #AvialableNumbers
FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
OPTION (MAXDOP 1);

CREATE UNIQUE CLUSTERED INDEX n ON #AvialableNumbers(n)

--Remove numbers that are in use.
delete #AvialableNumbers where n in (select Id from YourTable)

--Select the numbers out to the result set.
select n from #AvialableNumbers order by n

drop table #AvialableNumbers
";
    List<int> availableIDs = context.Database.SqlQuery<int>(query).ToList();

    /*
       Use the list of IDs here
    */

    context.SaveChanges();
    transaction.Commit();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM