Sql覆盖查询

时间:2016-01-19 12:28:00

标签: sql sql-server

我有表user_profilemoduleRole privilege_mapping
使用privilege_mapping表条目作为[ID,Module,privilege,userId,RoleID]

1 | Settings | true   | NULL  | 1  
2 | Settings | false  |   1   | 1  
3 | About    | true   | NULL  | 1  
4 | DashBoard| true   | NULL  | 1  

我要求某些用户的某些权限必须覆盖(开/关),而不是其角色权限。

对于eq:用户1具有角色ID 1.根据角色1设置被拒绝。但是我为用户启用了另一个已被启用的条目。

应该优先考虑用户权限。 所以用户1的权限应该是

2 | Settings  | false |  1   | 1  
3 | About     | true  | NULL | 1  
4 | DashBoard | true  | NULL | 1  

是sql查询的初学者。如何实现结果? 任何帮助将不胜感激

这是我到目前为止所做的。但现在它包含两行

;WITH prvCTE AS
(
    -- Insert statements for procedure here
    (
        SELECT module_id, url, privilege, module_name
        FROM [dbo].[UserProfile] U
        INNER JOIN [dbo].[privilege_mapping] P ON p.user_id = u.id
        INNER JOIN [dbo].[module] M ON p.module_id = M.id
        WHERE U.id = @userID


            EXCEPT

        -- Insert statements for procedure here
        SELECT module_id, url, privilege, module_name
        FROM [dbo].[UserProfile] U
        INNER JOIN [dbo].[role] R ON U.RoleID = R.RoleID
        INNER JOIN [dbo].[privilege_mapping] P ON p.role_id = R.RoleID
        INNER JOIN [dbo].[module] M ON p.module_id = M.id
        WHERE U.id = @userID
    )
    UNION

    SELECT module_id, url, privilege, module_name
    FROM [dbo].[UserProfile] U
    INNER JOIN [dbo].[role] R ON U.RoleID = R.RoleID
    INNER JOIN [dbo].[privilege_mapping] P ON p.role_id = R.RoleID
    INNER JOIN [dbo].[module] M ON p.module_id = M.id
    WHERE U.id = @userID
)
SELECT *
FROM prvCTE

1 个答案:

答案 0 :(得分:1)

行。我认为你需要考虑3种不同的情况:

  1. 用户存在,但用户没有UserPrivilege或RolePrivilege
  2. 用户存在,用户同时拥有UserPrivilege和RolePrivilege
  3. 用户存在,并且有一个
  4. 要在单个查询中考虑所有3个,您需要几个子查询和几个外部联接。

    SubQuery1:UserPrivileges

    要获得所有用户权限,我们提取:

    SELECT * FROM [dbo].[privilege_mapping] WHERE user_id IS NOT NULL
    

    SubQuery2:RolePrivileges

    要获得所有ROLE权限,我们使用此查询:

    SELECT * FROM [dbo].[privilege_mapping] WHERE user_id IS NULL
    

    将它们全部拉到一起:COALESCE()

    最后,要使用一个或另一个(取决于哪一个存在),我们使用COALESCE()语句。这种方式(我认为)我们可以在一个语句中完成整个选择:

    SELECT module_id, url, privilege=COALESCE(UP.privilege,RP.privilege), module_name
       FROM [dbo].[UserProfile] U
          LEFT OUTER JOIN (SELECT * FROM [dbo].[privilege_mapping] WHERE user_id IS NOT NULL) UP ON UP.user_id = U.id
          LEFT OUTER JOIN (SELECT * FROM [dbo].[privilege_mapping] WHERE user_id IS NULL) RP ON RP.role_id = U.role_id
          LEFT OUTER JOIN [dbo].[module] M ON COALESCE(UP.module_id,RP.module_id)=M.id
       WHERE U.id = @userID AND M.id IS NOT NULL
    

    <强>角色ID吗

    我在您的架构中遗漏了这个。不知道我怎么能告诉用户扮演一个给定的角色&#34;我假设用户表中有一个role_id,但无法从问题中得知。所以 - 我补充说,作为我们加入的领域。

    <强> MODULE吗

    行。我没有完整的架构,因此我不确定该模块的最后左外连接是否正常。我有一种感觉,我们需要另一个where子句去除NULL module_id&#39; s(例如WHERE module_id IS NOT NULL)。

    请注意,我们从LEFT OUTER JOIN拉出的字段上的子句很棘手(因为如果您对其进行错误编码,它可能会将连接转换为INNER JOIN)。

    试试这个。看看我们有多接近,然后我们就可以进行调整。