获取下一个未使用的ID?

3

目前我有一个不是由我管理的数据库,我无法对其进行任何更改,id字段是一个smallint 2 unsigned类型,可提供多达65535个id条目。

我的问题是,由于上述限制,我需要重新使用这些ID,我应该如何按顺序获取下一个可用的ID?或者,在上述限制下如何管理插入操作?

3个回答

8

检查是否有可用的1。如果没有:

SELECT MIN(a.id) + 1 AS smallestAvailableId
FROM your_table AS a
LEFT JOIN your_table AS a2
        ON a2.id = a.id + 1
WHERE a2.id IS NULL

2
如果数据库为空,则返回IFNULL(MIN(a.id) + 1,1)。 - Prix

2

根据标签推断您需要在Java中使用id。

我个人会避免将表与自身连接。由于最多只有64K行,我会在Java中从tableselect id并搜索id。一种找到间隔的方法是首先对数组进行排序(无论是在SQL还是在Java中),然后查找间隔变得简单。

如果您反复执行此操作,则可以缓存该数组,并避免每次需要id时运行SQL语句。

无论您做什么,如果有多个客户端正在向数据库写入,则必须准备处理竞争条件,即多个客户端将尝试使用相同的id。您的代码需要使用锁定或能够优雅地恢复以使用不同的id重新尝试失败的插入(我假设对id列存在唯一性约束。)


0
无论您采取哪种方法,由于竞态条件的存在,很可能会导致问题,除非您知道在任何单一时刻只有一个客户端访问数据库。
回答您的问题,您认为什么是“可用”的ID?请阐明一下。在所有ID都被使用之前,可以使用简单的方法。
SELECT MAX(id) + 1 FROM table;

应该这样做。如果您为“可用”ID建立了一个标准,例如重复使用所有已被标记为旧的ID,则可以执行以下操作:

SELECT MIN(id) FROM table WHERE is_old = 1; 

然后只需取消选定的ID标记。


我最初考虑的是要关注maxId,因为在它达到65535限制之前,我不需要重复使用ID,一旦max ID == 65535,那么我就需要检查未使用的ID。 - Prix
在这个上下文中,“unused”可能意味着“不存在具有此值的行”,这就是为什么Alin的SELF-JOIN检测NULL在这里如此优雅的原因。 - Konerak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接