可以CURRENT_TIMESTAMP
用作PRIMARY KEY
?
两个或更多不同的INSERT是否有可能获得相同的信息CURRENT_TIMESTAMP
?
可以CURRENT_TIMESTAMP
用作PRIMARY KEY
?
两个或更多不同的INSERT是否有可能获得相同的信息CURRENT_TIMESTAMP
?
Answers:
根据文档,的精度CURRENT_TIMESTAMP
为微秒。因此,碰撞的可能性低,但是可能。
现在想象这会发生的错误非常罕见,并导致数据库错误。调试有多难?它比至少具有确定性的错误要严重得多。
更广泛的上下文:您可能希望避免这些细微的差别,如果您习惯使用MySQL,这会特别烦人。
此外,如果您正在使用事务(大多数Web框架,尤其是Java框架都在使用!),那么事务中的时间戳将是相同的!演示:
postgres=# begin;
BEGIN
postgres=# select current_timestamp;
current_timestamp
-------------------------------
2018-08-06 02:41:42.472163+02
(1 Zeile)
postgres=# select current_timestamp;
current_timestamp
-------------------------------
2018-08-06 02:41:42.472163+02
(1 Zeile)
再见?两次选择,结果完全相同。我打得不太快。;-)
-
如果要轻松使用ID,避免使用序列,请从记录的真实标识符中生成一些哈希值。例如,如果您的数据库中有人类,并且您知道他们的出生日期,母亲的娘家姓和真实姓名唯一地标识了他们,则可以使用
md5(mother_name || '-' || given_name || '-' birthday);
作为ID。除此之外,您可以CreationDate
在对表建立索引之后使用一列,但这不是键(即id)。
Ps通常,最好使数据库具有尽可能好的确定性。也就是说,相同的操作应该在数据库中创建完全相同的更改。任何基于时间戳的ID都会使此重要功能失效。如果您想调试或模拟任何东西怎么办?您重播一个操作,并且将使用不同的id创建相同的对象 ……这确实不难遵循,并且节省了大量工作时间。
Ps2出于上述原因,将来任何人检查您的代码时,看到时间戳生成的ID都不会有最好的意见。
INSERT
多个行中的一个,则它们都会得到相同的current_timestamp
。然后您就有了触发器……
并非如此,因为CURRENT_TIMESTAMP可以为两个后续的INSERT(或具有多个行的单个INSERT)提供两个相同的值。
请改用基于时间的UUID:uuid_generate_v1mc()。
严格来说:否。因为CURRENT_TIMESTAMP
是一个函数,所以只有一个或多个表列可以构成PRIMARY KEY
约束。
如果要PRIMARY KEY
在具有默认值的列上创建约束CURRENT_TIMESTAMP
,那么答案是:是的,可以。没有什么可以阻止您这样做,就像没有什么可以阻止您从儿子的头上射出苹果一样。当您不定义问题的目的时,该问题仍然没有意义。列和表应该保存哪种数据?您尝试执行哪些规则?
通常,由于CURRENT_TIMESTAMP
该STABLE
函数会为同一笔交易返回相同的值(交易的开始时间),因此必然会遇到重复的键错误。同一事务中的多个INSERT必然会发生冲突-就像已经说明的其他答案一样。手册:
由于这些函数返回当前事务的开始时间,因此它们的值在事务期间不会更改。这被认为是一个功能:目的是允许单个事务具有“当前”时间的一致概念,以便同一事务内的多个修改具有相同的时间戳。
Postgres时间戳实现为8字节整数,最多可表示6个小数位(微秒分辨率)。
如果您要构建的表每秒钟只能容纳不超过一行,并且该条件不会改变(称为sensor_reading_per_microsecond
),则可能有意义。重复的行应该引发重复的键冲突错误。不过,这是一个奇特的例外。而且,数据类型timestamptz
(非timestamp
)可能更可取。看到:
我还是宁愿使用替代串行主键来代替。并UNIQUE
在时间戳列上添加一个约束。更少的麻烦,而不必依赖RDBMS的实现细节。
sensor_reading_per_microsecond
如果您不能绝对保证每次阅读的时间都与上一次完全同步,甚至可能会发生冲突。亚微秒的偏差(通常并非不可能)破坏了方案。总的来说,我还是会完全避免这种情况。(请注意,在这种情况下,您可能会希望引起碰撞!)