用于查找记录所有者的数据库模式
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_clients
和 team_clients
.
上加入它
您还可以将它与您的第一个选项结合起来,并为 user_clientsID
和 team_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;
我正在寻找一种模式来处理 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_clients
和 team_clients
.
您还可以将它与您的第一个选项结合起来,并为 user_clientsID
和 team_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;