我是否应该将我的 UUID 主键列称为 ID?

Big*_*oke 19 postgresql naming-convention uuid

我正在研究一种广泛使用UUIDs for PRIMARY KEYs 的数据库设计。然而,这让我面临一个非常重要的选择。我如何命名这些列?我会称它们uuid为 ,但UUID作为标识符,我必须在各处引用字段名称:

CREATE TABLE thingie (
  "uuid" UUID PRIMARY KEY DEFAULT public.gen_random.uuid(),
  foo VARCHAR,
  bar VARCHAR,
);
Run Code Online (Sandbox Code Playgroud)

一个直接的替代方案似乎是调用这些列id

CREATE TABLE thingie (
  id UUID PRIMARY KEY DEFAULT public.gen_random.uuid(),
  foo VARCHAR,
  bar VARCHAR,
);

Run Code Online (Sandbox Code Playgroud)

这样,我就没有列名,并且从语义上讲,我可以说 UUID 确实是一种 ID;在维恩图中,UUID 圆将完全放置在 ID 圆中。

然而,我(并且我相信许多其他人)已经习惯于id与自动递增INTEGER列关联,以至于我担心通过调用这些 ID 来打破某种不成文的规则id

如果您能通过一些可靠的自行车脱落来消除我的困惑,我将非常感激。事实上,我的问题是:会如何称呼你的-typed 代理键,为什么?UUID

Dav*_*ett 23

除了代理键是每行的唯一标识符这一事实之外,您不应该赋予代理键任何含义,因此从模式设计的角度来看,它采用什么格式并不重要。此时您应该关心的是它是一个标识某些内容的值,因此我坚持将它们称为ID\xe2\x81\xb0。

\n

事实上,你拥有的 UUID 实际上是一个大整数,除非你脑子有问题并将它们存储为 strings\xc2\xb9 。您无法对它\xc2\xb3 进行算术运算,但引擎不会将其视为与BIGINT用作密钥的更大值有任何不同。

\n

另一个一般性的事情是,我尝试避免任何可能是关键字的名称(对于列、表、函数、过程......),因此需要转义。uuid如果打电话给他们的要点id还不够的话,这是反对打电话给他们的一点。当然,这不可能是完美的,我会避免uuid,因为我知道它是 Postgres 中的类型名称,但到目前为止只使用过 SQL Server 的开发人员可能不知道,因为它不是保留字(甚至不是类型名称)在那里,我很可能会使用类似地不能在其他地方移植的单词。

\n

如果您由于与使用其他内容的另一个系统集成而有效地存储了多个代理键,则您的内部标识符为id。其他的是就您的系统而言有意义的真实数据,而不是实际的代理键,并且应该以描述其内容或用途的方式命名。现实世界的示例包括 ISBN、StaffReferenceNumber/SRN、IRN、PPN、\xe2\x80\xa6,但您可能还有一些不太通用的内容,例如 SalesForceId 或 JoesPartStoreId。即使您在这些情况下没有定义代理键\xe2\x81\xb4,也要保留有意义的名称,而不是仅仅这样id,很明显您的规则可能无法控制它们的生成和使用。

\n

[0] 或 id 或 Id,与您在其他地方遵循的大小写规则保持一致,以防您的内容最终以区分大小写的方式解释。

\n

[1] 我仍然维护着一个遗留系统,该系统在二十年前就犯了这个错误,比我的时代早了一点。这一切都有效,但当然还有存储大小和性能 \xe2\x80\x9cconsiderations\xe2\x80\x9d,并且有趣的 bug\xc2\xb2 导致无效的 UUID 值,例如出现空字符串。

\n

[2] 我还把过去的坏同事,包括多年前犯过几次这样的错误的年轻大卫·斯皮利特,算作是行业中的臭虫!

\n

[3] 好吧,如果你足够努力的话,你可以做到,但不是使用任何内置函数。

\n

[4] 无论如何,在这些情况下我总是有一个代理键。这意味着只有您的错误才会导致重复键等问题,或者需要进行昂贵的主键值更改(影响许多外键),而不是还要处理其他系统的错误。

\n


Erw*_*ter 21

“uuid”不是SQL关键字。既不在标准 SQL 中,也不在PostgreSQL中。它是数据类型uuid的名称- 从技术上讲,它并不反对使用“uuid”作为标识符(即使没有双引号)。

自 SQL:2011 起, “id”是标准 SQL 中的非保留关键字。但非保留关键字可以自由地用作标识符。

所以你可以使用其中任何一个。并不意味着你应该这样做。我个人的观点是“id”(以及“uuid”)不是足够描述性的名称。我认为“id”的广泛使用是一种反模式。关系数据库中的任何重要查询都会连接多个表。然后你最终会得到多个列,全部命名为“id”,并且你必须对表进行限定或处理别名。虽然您仍然可以(甚至应该)这样做,但最好不要这样做。

最重要的是,我避免使用基本类型名称作为标识符。不必要的混乱。令人困惑的错误消息、搜索问题、拼写错误陷阱等。

使用描述性的、合法的、小写的、不带引号的标识符,尽可能短,只要必要即可。
有关的:

我的首选命名模式是使用“foo_id”作为名为“foo”的表的代理主键列的名称。它是我的foo实体的ID,无论其数据类型如何。我对引用它的任何外键列使用相同的名称(具有相同的内容)。列上的标签代表其中的内容,查询一目了然。快速即席查询可以使用.USING (foo_id)

我通常不会在列名称中包含数据类型。(除非这是该术语的常见做法。)这太吵了。我不将我的价格列称为“price_numeric”,也不将我的姓名列称为“surname_text”。如果您必须将foo_id列的数据类型从integer更改为 ,该怎么办bigint?您不想更改列名称并将该更改传播到所有编写的代码......

因此,我使用 "foo_id",而不是"uuid""id_uuid"。普通用户只需要知道“foo_id”是表“foo”的唯一(PK)ID列。数据类型是对特殊/高级目的感兴趣的实现细节。

  • @BigSmoke:我只为 PK 加上前缀,并且仅当名称像“id”这样常见时才添加前缀。我认为给所有列名称添加前缀太吵了,似乎我们在那里达成了一致。 (4认同)