在我目前的 Rails 应用程序中,我通过按“ created_at
”字段对模型进行排序来解决调度冲突。但是,我意识到,当从允许这样做的表单中插入多个模型时,所有created_at
时间都是完全相同的!
这更像是一个最佳编程实践的问题:您的应用程序是否可以依赖数据库中的 ID 列来越来越大地递增,INSERT
以获得它们的创建顺序?换句话说,我可以按 ID 列对从数据库中提取的一组行进行排序,并确保这是基于创建顺序的准确排序吗?这是我的应用程序中的一个好习惯吗?
在我目前的 Rails 应用程序中,我通过按“ created_at
”字段对模型进行排序来解决调度冲突。但是,我意识到,当从允许这样做的表单中插入多个模型时,所有created_at
时间都是完全相同的!
这更像是一个最佳编程实践的问题:您的应用程序是否可以依赖数据库中的 ID 列来越来越大地递增,INSERT
以获得它们的创建顺序?换句话说,我可以按 ID 列对从数据库中提取的一组行进行排序,并确保这是基于创建顺序的准确排序吗?这是我的应用程序中的一个好习惯吗?
生成的标识号将是唯一的。无论您是使用 PostgreSQL 和 Oracle 中的序列,还是使用其他机制(如 MySQL 的自动增量)。
然而,序列通常是批量获取的,例如 20 个数字。因此,使用 PostgreSQL,您无法确定首先插入哪个字段。插入记录的 id 甚至可能存在间隙。
因此,您不应将生成的 id 字段用于此类任务,以免依赖数据库实现细节。
在命令执行期间生成创建或更新的字段对于稍后按创建时间或更新时间进行排序要好得多。例如:
INSERT INTO A (data, created) VALUES (smething, DATE())
UPDATE A SET data=something, updated=DATE()
这取决于您的数据库供应商。
MySQL 我相信绝对会订购自动增量键。SQL Server 我不确定它是否存在,但我相信它确实存在。
您会遇到问题的地方是不支持此功能的数据库,最值得注意的是使用序列的 Oracle,这些序列是粗略但不是绝对有序的。
另一种方法可能是先创建时间,然后再进行 ID。
我相信您的问题的答案是肯定的...如果我在字里行间阅读,我认为您担心系统可能会重新使用序列中“缺失”的 ID 编号,因此如果您使用了 1, 2,3,5,6,7 作为 ID 号,在我知道的所有实现中,下一个 ID 号将始终为 8(或可能更高),但我不知道有任何数据库会尝试找出该记录 ID #4 丢失,因此请尝试重新使用该 ID 号。
虽然我最熟悉 SQL Server,但我不知道为什么任何供应商都尝试按顺序填补空白 - 想想保留未使用 ID 列表的开销,而不是始终跟踪最后一个 I使用的数字,并加 1。
我想说你可以放心地依赖下一个分配的 ID 编号总是高于上一个 - 不仅仅是唯一的。
是的,id 将是唯一的,不,您不能也不应该依赖它进行排序 - 它只是为了保证行的唯一性。正如 emktas 所指出的,最好的方法是使用单独的“更新”或“创建”字段来存储此信息。
要设置创建时间,您可以使用这样的默认值
CREATE TABLE foo (
id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL;
created TIMESTAMP NOT NULL DEFAULT NOW();
updated TIMESTAMP;
PRIMARY KEY(id);
) engine=InnoDB; ## whatever :P
现在,这需要处理创建时间。对于更新时间,我建议使用像这样的 AFTER UPDATE 触发器(当然您可以在单独的查询中执行此操作,但在我看来,触发器是一个更好的解决方案 - 更透明):
DELIMITER $$
CREATE TRIGGER foo_a_upd AFTER UPDATE ON foo
FOR EACH ROW BEGIN
SET NEW.updated = NOW();
END;
$$
DELIMITER ;
那应该这样做。
编辑:不幸的是我。愚蠢的是,我没有指定这是针对 mysql 的,函数名称(即“NOW”)和其他细微之处可能存在一些差异。
EJB 回答的一个警告:
如果您不按列指定顺序,SQL 不提供任何顺序保证。例如,如果您删除了一些早期的行,然后插入它们,那么新的行可能最终会与旧的行在数据库中的相同位置(尽管使用新的 ID),这就是它可以用作默认排序的方式。
FWIW,我通常使用 ID 订单作为 created_at 订单的有效版本。它更便宜,因为它不需要向日期时间字段添加索引(它比简单的整数主键索引更大,因此比简单的整数主键索引更慢),保证是不同的,而且我真的不在乎是否有几行大约在同一时间添加,以稍微不同的顺序排序。
这可能取决于数据库引擎。我会检查你的数据库是如何实现序列的,如果没有记录的问题,那么我会决定依赖 ID。
例如,除非您使用序列缓存参数,否则Postgresql 序列是可以的。
其他程序员可能会手动创建或复制来自具有错误 ID 列的不同数据库的记录。但是我会简化问题。不要担心有人会手动破坏数据完整性的低概率情况。你无法防范一切。
我的建议是依靠序列生成的 ID 并推进您的项目。
理论上是的,最高的 id 号是最后创建的。请记住,尽管数据库确实有能力暂时关闭自动生成值的插入,手动插入一些记录,然后再将其重新打开。这些插入通常不用于生产系统,但在从另一个系统移动大量数据时偶尔会发生。