查询用户对应用程序模块的访问权限

时间:2015-03-24 12:31:07

标签: sql-server sql-server-2012

我必须创建一个查询,它将返回用户和他们有权访问的应用程序模块。除了用户和模块列表外,如果该用户无法访问任何模块,则查询也应返回。

'ApplicationUsers'表是这样的:

CREATE TABLE #ApplicationUsers
(
userId INT,
UserName VARCHAR(50)
)
INSERT INTO #ApplicationUsers VALUES
(1, 'Daniel'), (2,'Martin'), (3, 'Brandon'), (4, 'Doug')

'ApplicationModule'表是这样的:

CREATE TABLE #ApplicationModules
(
moduleId INT,
moduleName VARCHAR(50)
)
INSERT INTO #ApplicationModules VALUES
(1, 'Sales'), (2, 'Production'), (3, 'Marketing')

这是我们在'ModuleAccess'表中为用户存储模块访问的方式:

CREATE TABLE #ModuleAccess
(
Id INT,
userId INT,
moduleId INT
)
INSERT INTO #ModuleAccess VALUES
(1, 1, 1), (2, 1, 3), (3, 2, 1), (4, 2, 2), (5, 3, 2)

在上面的例子中,'Daniel'只能访问'Sales'和'Marketing','Martin'可以访问'Sales'和'Production'等等。所以所需的输出是:

CREATE TABLE #ExampleOutput
(
[userName] VARCHAR(50),
[Sales] VARCHAR(5),
[Production] VARCHAR(5),
[Marketing] VARCHAR(5)
)
INSERT INTO #ExampleOutput VALUES 
('Daniel', 'true', 'false', 'true'),
('Martin', 'true', 'true', 'false'),
('Brandon', 'false', 'true', 'false'),
('Doug', 'false', 'false', 'false')

SELECT * FROM #ExampleOutput

我使用了数据透视查询,但它有一些限制(可能是我在制作错误)。首先,pivot列是静态的,而我需要动态列名(Application Modules)。其次,我需要包含所有具有访问权限的模块的所有用户,或者无法访问我无法访问的模块。有人可以写一个示例查询来帮助我如何做到这一点吗?

2 个答案:

答案 0 :(得分:0)

如果您坚持使用问题中所述的表格设计,这将有效。

(SELECT username, am.moduleName AS Module, CAST(0 AS BIT) AS HasAccess
FROM #ApplicationUsers AS au INNER JOIN #ApplicationModules AS am ON 1 = 1
EXCEPT
SELECT username, am.moduleName AS Module, CAST(0 AS BIT) AS HasAccess
FROM #ApplicationUsers AS au INNER JOIN #ModuleAccess AS ma ON ma.userId = au.userId INNER JOIN #ApplicationModules AS am ON am.moduleId = ma.moduleId)
UNION 
SELECT username, am.moduleName AS Module, CAST(1 AS BIT) AS HasAccess
FROM #ApplicationUsers AS au INNER JOIN #ModuleAccess AS ma ON ma.userId = au.userId INNER JOIN #ApplicationModules AS am ON am.moduleId = ma.moduleId
ORDER BY 1, 2

虽然有笛卡尔加入" 1 = 1"不太好的解决方案。如果你能够修改ModuleAccess表并包含一个" HasAccess BIT NOT NULL DEFAULT(0)"列,并让应用程序包含新用户的所有模块。如果用户没有访问权限,则将新列设置为零,如果他们有访问权限,则将其设置为1。

答案 1 :(得分:0)

如果有人有类似的要求,这是工作查询:

DECLARE @DynamicPivotQuery AS NVARCHAR(MAX)
    DECLARE @ColumnName AS NVARCHAR(MAX)

    SELECT @ColumnName = ISNULL(@ColumnName + ',', '') + QUOTENAME([moduleName])
    FROM (
        SELECT DISTINCT [moduleName]
        FROM #ApplicationModules
        ) AS ApplicationModules

    SET @DynamicPivotQuery = '
SELECT * FROM
(
SELECT D.[moduleId], D.[moduleName], U.[UserName] AS [User] FROM 
#ApplicationUsers U
LEFT OUTER JOIN #ModuleAccess DA
ON U.[userId] = DA.[userId]
LEFT OUTER JOIN #ApplicationModules D
ON D.[moduleId] = DA.[moduleId]
) A
pivot (MIN(moduleId)for [moduleName] in (' + @ColumnName + ')) as [moduleIdId]
'

    EXEC sp_executesql @DynamicPivotQuery

    DROP TABLE #ApplicationUsers
    DROP TABLE #ModuleAccess
    DROP TABLE #ApplicationModules