我有一个查询,我在其中检查用户是否具有烫发列表中的所有权限。
所以,就像这样......
SELECT DISTINCT account_id
FROM pp_acl_user_roles ur, pp_acl_role_permissions rp
JOIN pp_acl_permissions p ON rp.permission_id=p.id
WHERE (
ur.account_id = '1'
#check for permission ids OR keys depending on what has been passed in.
AND ( p.id IN ('read_accounts', 'write_accounts') OR p.key IN ('read_accounts', 'write_accounts') )
AND ur.role_id = rp.role_id
)
#ensure we have ALL the permissions we asked for, not just some -makes IN() an AND not an OR.
GROUP BY ur.account_id
HAVING COUNT(DISTINCT rp.permission_id) = 2
它检查id
的列表或keys
的权限列表,因此可以使用其中任何一个来调用它,所以这一行。
p.id IN ('read_accounts', 'write_accounts') OR p.key IN ('read_accounts', 'write_accounts')
可能是
p.id IN (1, 2) OR p.key IN (1, 2)
取决于它的调用方式。
最后HAVING
确保我们匹配所有我们要求的项目。
这很好,但是我想把它移到存储过程中,我遇到了一个问题。
我必须为IN
更改FIND_IN_SET
所以我可以将字符串列表传递给过程,但问题是,我无法动态计算很多的方式项目在列表中,所以我无法检查它们是否全部存在。
CREATE PROCEDURE has_permission( IN account_id BIGINT, IN permissions TEXT )
BEGIN
SELECT DISTINCT account_id
FROM pp_acl_user_roles ur, pp_acl_role_permissions rp
JOIN pp_acl_permissions p ON rp.permission_id=p.id
WHERE (
ur.account_id = account_id
#check for permission ids OR keys depending on what has been passed in.
AND ( FIND_IN_SET(p.id, permissions) OR FIND_IN_SET(p.key, permissions) )
AND ur.role_id = rp.role_id
)
#ensure we have ALL the permissions we asked for, not just some -makes IN() an AND not an OR.
GROUP BY ur.account_id;
HAVING COUNT(DISTINCT rp.permission_id) = ????????????
END //
DELIMITER ;
但是没有办法计算传入的权限的长度。
我确信有一种方法可以根据字符串中的项目加入perms表,并确保我们在两个表中都有匹配,但我无法解决它。
任何指针都非常赞赏...
答案 0 :(得分:0)
这是我到目前为止所得到的......
不太理想,但你可以用这个来计算字符串中项目的长度..
(SELECT LENGTH(permissions) - LENGTH( REPLACE(permissions, ',', '') ) + 1)
它基本上计算字符串中的所有逗号,并将其用作传入的perms总数。
CREATE PROCEDURE has_permission( IN account_id BIGINT, IN permissions TEXT)
BEGIN
SELECT DISTINCT account_id
FROM pp_acl_user_roles ur, pp_acl_role_permissions rp
JOIN pp_acl_permissions p ON rp.permission_id=p.id
WHERE (
ur.account_id = account_id
#check for permission ids OR keys depending on what has been passed in.
AND ( FIND_IN_SET(p.id, permissions) OR FIND_IN_SET(p.key, permissions) )
AND ur.role_id = rp.role_id
)
#ensure we have ALL the permissions we asked for, not just some -makes IN() an AND not an OR.
GROUP BY ur.account_id
HAVING COUNT(DISTINCT rp.permission_id) = (SELECT LENGTH(permissions) - LENGTH( REPLACE(permissions, ',', '') ) + 1);