具有可为空外键的数据库 table

Database table with nullable foreign key

我正在为我的网站创建一个新的数据库设计。我的数据库中有两种类型的用户。所以我有 user_t 并且它与 client_t 相关联。一个用户可以有多个客户端。现在我有 app_t。一个客户可以拥有多个应用程序。

这个app_t可以由客户端和用户更新。我正在为 app_t 创建审核试验 table,我不想在 updated_by[=27= 中存储名称] 因为它可能会改变。相反,我想将 client_iduser_id 作为列。在这种情况下,当客户端更新 table user_id 列时将为空,而当用户更新 table client_id 将为空。这两个 id 都是外键,它们引用各自 table 的主键列。有这样的空值可以吗?

提前致谢。

Is it okay to have such null values?

这是主观的。问题是:你能用它工作吗?可能是。但是能保证完整性吗?编号

那么会出什么问题呢?您可以设置两个外键,也可以同时保留两个 NULL - 数据库不会抱怨。在这两种情况下,您都不知道谁更新了该项目。

另一种方法是始终设置 user_id(NOT NULL)并让 client_id 是可选的。如果 client_id 为 NULL,您知道 - 它由用户更新。如果它不是 NULL,那么你知道 - 它由客户端更新。

然后您可以通过以下方式检索名称:

select at.*, coalesce(c.name, u.name) as updated_by
from app_audit at
join user_t u        on u.id = at.user_id
left join client_t c on c.id = at.client_id

但事情仍然可能出错。您可以保存不是应用程序 "owner" 的客户的 ID。 user_id也是如此。由于设计(审计跟踪 -> 应用程序 -> 客户端 -> 用户),client_iduser_id 在功能上都依赖于 app_id。所以实际上你所需要的只是 app_id 作为外键和一个布尔标志,它告诉你它是由用户还是客户端更新的。然后您将检索数据:

select at.*, coalesce(u.name, c.name) as updated_by
from app_audit at
join app_t a       on a.id = at.app_id
join client_t c    on c.id = a.client_id
left join user_t u on u.id = c.user_id  and a.updatet_by_user = 1

关于您的评论:

我不相信 "best approach" 或 "best practice" 这样的东西,当问题是 "complex enough" 时。那么问题是 - Best 有什么用?通常您有多个目标,例如 清晰度简单性可用性灵活性可靠性性能,可能还有更多。灵活性的 "best approach" 可能是性能的噩梦,反之亦然。

一个更广泛使用的术语是“良好实践”。 数据库规范化被认为是好的做法。添加 user_idclient_id 在非 candidate key, which violates 3NF.

上引入 功能依赖性

另一方面,如果没有这些列,您需要在 SELECT 查询中再添加一个 JOIN。但只要不是很重要,我就不会太在意。