2009-07-01 86 views
2

我在web应用中实施家庭酿造ACL系统,它给我很难。我相信这是微不足道的,只是无法摆脱它。加入查询时遇到问题

我有一个3个表一对多的关系:
resourceperms_groupperms_users 其中perms_group是一个关键的表,而如果需要perms_users allowes我每用户的基础上微调访问(这加起来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用户3 ,如果有任何设置。基本上我缺少AND_IF_EXISTS运算符;)。我可以很容易地在两个查询中分解它,但是因为它会在每次页面刷新时运行,所以我需要尽可能精简它。目前我正在使用MySQL,但稍后想要切换到PostgreSQL,所以理想的解决方案将独立于数据库。有任何想法吗?

感谢

回答

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 

事实上,左外连接是无用的,如果你写在桌子上的情况,当你不知道你是否有数据。

0

如果您将您的权限连接(左外连接)为一行,则可以使用CASECOALESCE来实现您所需的内容。

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  
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_users中找到记录,它甚至不会查看perms_groups