Joh*_*kin 15 postgresql database-design primary-key timestamp
可以CURRENT_TIMESTAMP用作PRIMARY KEY?
是否有可能两个或多个不同的 INSERT 得到相同的结果CURRENT_TIMESTAMP?
pet*_*erh 20
根据文档,精度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)
Run Code Online (Sandbox Code Playgroud)
再见?两次选择,完全一样的结果。我打字没那么快。;-)
——
如果你想要简单的 ID,避免使用序列,然后从记录的真实标识符生成一些哈希值。例如,如果您的数据库中有人类,并且您知道他们的出生日期、母亲的婚前姓名和真实姓名可以唯一地标识他们,那么使用
md5(mother_name || '-' || given_name || '-' birthday);
Run Code Online (Sandbox Code Playgroud)
作为身份证。除此之外,您可以CreationDate在索引表之后使用一列,但它不是键(即 id)。
Ps 一般来说,尽可能使您的数据库具有确定性是一个非常好的做法。即相同的操作应该在 DB 中创建完全相同的更改。任何基于时间戳的 ID 都无法实现这一重要功能。如果您想调试或模拟任何东西怎么办?你重放一个操作,会用不同的id创建同一个对象……这真的不难理解,而且节省了很多工作时间。
Ps2 由于上述原因,将来任何人检查您的代码时,都不会看到时间戳生成的 ID 的最佳意见。
小智 10
并不是因为 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(not timestamp) 可能更可取。看:
我仍然宁愿使用代理串行主键。并UNIQUE在时间戳列上添加约束。更少可能的并发症,不依赖于 RDBMS 的实现细节。
| 归档时间: |
|
| 查看次数: |
7987 次 |
| 最近记录: |