用于查找记录所有者的数据库模式

Db pattern for finding the owner of a record

我正在寻找一种模式来处理 table 中的一条记录可能与 1 相关且仅与其他几条记录中的一条相关的情况,我需要知道是哪一条。这很难描述,所以我将使用一个来自最近项目的 oauth 客户端的示例。

客户有一个 ID 和秘密,团队或用户可以拥有客户

clients
client_id|client_secret

user_clients
user_id|client_id

team_clients
team_id|client_id

这里的问题是当有人试图使用客户端凭据来获取访问令牌时,我需要知道这些凭据是属于团队还是用户。我不确定处理此问题的最佳方法,我控制着数据库,因此可以进行更改。

我考虑过的一些选项:

Modify clients and remove user_clients and team clients

clients
client_id|client_secret|team_id(nullable)|user_id(nullable)
Create a client owners table and remove user_clients and team_clients

client_owners
team_id(nullable)|user_id(nullable)|client_id
Adding a type to the clients table and doing 2 queries or a conditional query

clients
client_id|client_secret|type(user or team)

Left joins and filtering/mapping in code.

select * from clients c left join user_clients u ... left join team_clients t ... where c.client_id = ?

None 这些选项感觉很棒所以我想知道是否有更好的模式。这是一个简化的示例,有时这些对象要复杂得多并且有更多可能的关系,因此在使用 orm 时查询会变得非常复杂并且也难以管理(尽管系统的某些部分需要原始 sql不是问题)。

我很想听听人们是如何解决这个问题的。

提前致谢。

左连接的想法是你可以接受的。将您的 clients table 留在 clientID 上,然后在 user_clientsteam_clients.

上加入它

您还可以将它与您的第一个选项结合起来,并为 user_clientsIDteam_clientsID 添加一列,并添加到左连接 clients.user_clientsID <> 0 这将帮助您.

第二个和第三个选项也是我见过的。第二种选择有时可能是最令人头疼的选择。

您还可以考虑创建一个包含您可能需要的所有信息的视图table

设计

你描述的是1:n关系:

  • 一个用户可以拥有多个客户端
  • 一个团队可以拥有多个客户

因此,第一种方法是合适的:客户端 table 有一个用户列和一个客户列。

现在您说客户只能由用户客户拥有。为此,您将在客户端 table 上进行检查约束,以确保只设置了一个 ID。 (如果每个客户 必须 有一个所有者,这个约束也会关心这个。)

一些示例查询

如果你想获得用户拥有的所有客户:

select * from clients where user_id is not null;

如果您想知道客户端是属于用户还是团队:

select
  c.*,
  case when user_id is not null then 'user' 
       when team_id is not null then 'team' 
                                else 'none'
  end as owner
from clients c;

如果您需要用户或团队信息:

select c.*, coalesce(u.name, t.name) as owner_name
from clients c
left join users u on u.user_id = c.user_id
left join teams t on t.team_id = c.team_id;