我正在网络应用中实现家庭酿造ACL系统,这让我很难过。我相信这是微不足道的,只是无法理解它。
我有一对多关系中的3个表:
resource
,perms_group
,perms_users
其中perms_group
是一个关键表,而perms_users
允许我根据需要微调每个用户的访问权限(它加起来perms_users
或只是简单地覆盖它,两个表都将权限存储为布尔值在单独的列中)。
我正在尝试从资源中获取内容以及在单个查询中获取权限:
SELECT *
FROM resource
LEFT OUTER JOIN perms_groups ON resource.id = perms_group.res_id
LEFT OUTER JOIN perms_users ON resource.id = perms_users.res_id
WHERE resource.id = 1
AND perms_group.group_id = 2
AND perms_users.user_id = 3
现在麻烦的是很少设置用户的精细权限,在这种情况下,上面的查询将返回0行。我要告诉的是,如果有任何设置,请为第2组和用户3 取回权限。基本上我缺少AND_IF_EXISTS
运算符;)。我可以轻松地在两个查询中打破它,但因为它会在每次刷新页面时运行,所以我需要尽可能精简。目前我正在使用MySQL,但我希望稍后切换到PostgreSQL,因此理想的解决方案将是db独立的。有什么想法吗?
由于
答案 0 :(得分:4)
SELECT *
FROM resource
LEFT OUTER JOIN perms_groups ON resource.id = perms_group.res_id
AND perms_group.group_id = 2
LEFT OUTER JOIN perms_users ON resource.id = perms_users.res_id
AND perms_users.user_id = 3
WHERE resource.id = 1
事实上,如果你在不知道自己是否有数据的情况下在桌子上写条件,那么左外连接是没用的。
答案 1 :(得分:1)
您可以尝试将WHERE子句移动到用户的联接中。群组...
SELECT *
FROM resource
LEFT OUTER JOIN perms_groups ON resource.id = perms_group.res_id AND perms_group.group_id = 2
LEFT OUTER JOIN perms_users ON resource.id = perms_users.res_id AND perms_users.user_id = 3
WHERE resource.id = 1
答案 2 :(得分:0)
如果您将权限加入(左外连接)一行,则可以使用CASE
或COALESCE
来实现所需内容。
答案 3 :(得分:0)
如果您的用户权限覆盖了组权限,请使用以下命令:
SELECT permission
FROM resource
JOIN perms_users
ON perms_users.res_id = resource.id
WHERE resource.id = 1
AND user_id = 3
UNION ALL
SELECT permission
FROM resource
LEFT JOIN
perms_groups
ON perms_group.res_id = resource.id
AND group_id = 2
WHERE resource.id = 1
LIMIT 1
这会更有效率,因为如果perms_groups
中找到记录,此查询甚至不会查看perms_users
。
答案 4 :(得分:0)
为了更好地理解外连接,请阅读: