如何防止此访问控制SQL查询返回重复项?

时间:2014-09-16 06:42:07

标签: sql

我们有一个包含Widgets表的数据库。每个Widget只能由具有正确角色的用户查看。可以授予多个角色查看每个窗口小部件的权限。

表格如下:

的widget

Widget_Id
        1

权限

Widget_Id | Role_Id
        1 |       1
        1 |       2

角色

Role_Id | User_Id
      1 |       1
      2 |       1

用户

User_Id
      1

现在让我们说我想找到允许给定用户看到的所有小部件:

SELECT *
 FROM Widget
JOIN Permission USING(Widget_Id)
WHERE Role_Id IN (
  SELECT Role_Id
    FROM Role
    JOIN User
    WHERE User_Id = 1)

这里的问题是Widget被授予了几个角色,而用户拥有多个角色。如何阻止查询返回同一个Widget的多个重复项,每个角色一个? (请注意,我不想使用DISTINCTROW_NUMBER OVER(PARTITION...)技巧。我发现大表的性能会显着降低。

2 个答案:

答案 0 :(得分:3)

使用WHERE EXISTS构造。这可以保证您不会看到重复的小部件。

SELECT * FROM Widget w
WHERE EXISTS
     (SELECT 1 FROM Permission p
      JOIN Role r ON r.Role_ID = p.Role_ID
      JOIN User u ON u.User_ID = r.User_ID
      WHERE p.Widget_ID = w.Widget_ID
      AND u.User_ID = ?)

答案 1 :(得分:1)

如果您的架构如下:

create table Widget (Widget_Id int, Widget_Name varchar(50));
create table Permission (Widget_Id int,Role_Id int);
Create table Roles (Role_Id int, [User_Id] int);
Create table Users ([User_Id] int, [User_Name] varchar(50));
go

数据样本如下:

insert into WIDGET Values(1, 'W1');
insert into WIDGET Values(2, 'W2');
insert into PERMISSION Values(1,1);
insert into PERMISSION Values(1,2);
Insert into ROLES Values(1,1);
Insert into ROLES Values(2,1);
Insert into USERS Values(1,'U1');
Insert into USERS Values(2,'U2');
Go

为给定用户提供单组允许小部件的脚本将是:

SELECT *
 FROM Widget W
WHERE W.WIDGET_ID   IN (
  SELECT P.WIDGET_ID
    FROM Roles R
    JOIN Permission P on R.ROLE_ID=P.ROLE_ID
    JOIN Users U ON R.USER_ID=U.USER_ID
    WHERE U.User_Id = 1)