将列表传递到MySQL存储过程并检查所有值是否存在

时间:2016-06-23 13:22:40

标签: mysql stored-procedures

我有一个查询,我在其中检查用户是否具有烫发列表中的所有权限。

所以,就像这样......

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表,并确保我们在两个表中都有匹配,但我无法解决它。

任何指针都非常赞赏...

1 个答案:

答案 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);