5

(与查找列表中最低未使用的唯一 ID获取 SQL 表上未使用的唯一值有关

假设我有一个包含 id 列和其他一些列的表(它们在这里没有任何区别):

+-----+-----+
| id  |other|
+-----+-----+

id 具有数值递增的值。我的目标是获得最低的未使用 id 并创建该行。所以当然我第一次运行它会返回0并且该行的行将被创建。执行几次后,它将如下所示:

+-----+-----+
| id  |other|
+-----+-----+
|  0  | ... |
|  1  | ... |
|  2  | ... |
|  3  | ... |
|  4  | ... |
+-----+-----+

很多时候,其中一些行可能会被删除。让我们假设 id 为1和的行3已被删除。不,表格将如下所示:

+-----+-----+
| id  |other|
+-----+-----+
|  0  | ... |
|  2  | ... |
|  4  | ... |
+-----+-----+

如果我现在再次运行查询,它想取回 id1并且应该创建此行:

| id  |other|
+-----+-----+
|  0  | ... |
|  1  | ... |
|  2  | ... |
|  4  | ... |
+-----+-----+

下次运行查询时,它应该返回 id 的3, 5,6等。

运行这些查询的最有效方法是什么,因为我需要在一秒钟内经常执行它们(可以公平地假设 id 是表的唯一目的)?是否可以通过一个查询获得下一个未使用的行?或者通过引入另一个跟踪未使用的 id 的表是否更容易和更快?

如果它明显更快,那么只要所有数字在某个时间被重用,也有可能获得一种重用表中任何孔的方法。

额外的问题:我计划使用 SQLite 来存储这种信息,因为除了存储这些 id 之外我不需要数据库。是否有任何其他免费(如语音)服务器可以更快地完成这项工作?

4

4 回答 4

3

我想我会在删除时创建一个触发器,并将 old.id 插入一个单独的表中。然后您可以从该表中选择 min(id) 以获得最低的 id。

免责声明:我不知道您使用什么数据库引擎,所以我不知道您是否可以使用触发器。

于 2010-08-25T18:10:24.280 回答
2

数据库不关心这些值是否是顺序的,只关心它们是唯一的。让您的id值连续的愿望纯粹是装饰性的,如果您将此值公开给用户 - 它不应该是您的主键,也不应该有任何基于该值的引用完整性,因为客户端可以根据需要更改格式.

处理 id 值生成的最快和最安全的方法是依赖为您提供唯一整数值​​的本机功能(IE:SQLite 的自动增量)。使用触发器只会增加开销,使用 MAX(id) +1 是非常危险的......

概括

理想情况下,使用本机唯一整数生成器(SQLite/MySQL auto_increment、Oracle/PostgreSQL 序列、SQL Server IDENTITY)作为主键。如果您想要一个始终连续的值,请添加一个额外的列来存储该连续值并根据需要对其进行维护。MySQL/SQLite/SQL Server 唯一整数生成只允许每列一个 - 序列更灵活。

于 2010-08-25T18:14:02.913 回答
2

就像丹尼斯·哈布林克所说的那样;删除触发器和插入触发器:

删除触发器将获取已删除的 id 并将其插入到 id 池表中(只有一列id

插入之前的触发器将检查是否提供了 id 值,否则它只是查询 id 池表(例如:SELECT MIN(id) FROM id_pool_table)并分配它(ig 将其从 id_pool_table 中删除)

于 2010-08-25T18:14:53.933 回答
1

通常你会让数据库处理分配ID。是否有特殊原因需要 id 的顺序而不是唯一的?相反,您可以给它们加上时间戳,并在显示它们时给它们编号吗?或者为顺序ID创建一个单独的列,然后重新编号?

或者,您不能删除行本身,而是在列中使用标志将它们标记为已删除,然后通过查找编号最小的“已删除”行并重用该 ID 来重用标记行的 ID。

于 2010-08-25T18:13:51.977 回答