【发布时间】:2012-08-01 19:35:49
【问题描述】:
我先搜索了几次,还有一个问题。
不知不觉,我找到的最佳答案在this SO 答案中。总结:
SELECT * FROM TABLE WHERE ID = (SELECT MAX(ID) FROM TABLE);
我想知道的是下面的方法是否也能正常工作(因为我懒得改变它,我碰巧喜欢它)。
SELECT * FROM TABLE ORDER BY ID DESC LIMIT 1
根据我们拥有的SQLite Autoincrement 文档,
如果插入时没有指定 ROWID,或者指定的 ROWID 的值为 NULL,则会自动创建适当的 ROWID。 通常的算法是给新创建的行一个比插入前表中最大的 ROWID 大一的 ROWID。如果表最初为空,则使用 1 的 ROWID。 [强调]
还有,
只要您从不使用最大 ROWID 值并且从不删除表中具有最大 ROWID 的条目,上述正常 ROWID 选择算法将生成单调递增的唯一 ROWID。 如果您曾经删除过行,或者曾经创建过具有最大可能 ROWID 的行,那么在创建新行时可能会重复使用先前删除的行中的 ROWID,并且新创建的 ROWID 可能不会严格按照升序排列。 [强调]
关于我提出的 SQL 语句的问题来自最后一句话。这似乎表明,如果您删除任何行,则可以重用先前删除的 ROWID,而不管是否使用了最大 ROWID。如果我们假设从未使用过最大 ROWID(手动或仅通过那么多记录),那么我们只需要担心删除记录。在这种情况下,第一个 SQLite 文档摘录听起来好像您不会在我的查询中遇到任何问题。
有人确定吗?
我喜欢我的查询,因为它只涉及一个选择(虽然,以订购为代价)。我想,我可能过于关注微小的优化,不是吗?
编辑: 实际上,重新查看上面引用的 SQLite 页面,我认为使用 AUTOINCREMENT 关键字可以保证 ROWID 单调递增。最后一节详细讨论了它。
如果列的类型为 INTEGER PRIMARY KEY AUTOINCREMENT,则使用稍微不同的 ROWID 选择算法。为新行选择的 ROWID 至少比以前存在于同一个表中的最大 ROWID 大一个。如果表以前从未包含任何数据,则使用 1 的 ROWID。如果该表之前保存了具有最大可能 ROWID 的行,则不允许新的 INSERT,并且任何插入新行的尝试都将失败并返回 SQLITE_FULL 错误。
现在对我来说似乎很清楚。只是无法填满表格(最多 9223372036854775807)。
对不起,我之前只略过这部分!
【问题讨论】:
-
我没有发现问题。你的逻辑对我来说是合理的。重用 ROWID 背后的想法似乎是优化表空间和偏移量。
-
如果您想保证选择最后一行的方法,请使用时间戳而不是
ROWID。 (假设您没有及时旅行或将系统时钟设置为过去) -
@Sam 可能会比我的方法更好,因为使用自动递增 rowid 字段会使插入速度变慢。不过,对于大多数应用程序,我敢打赌这无关紧要。