У нас есть структура наследования ролей, где вместо фильтрации самого высокого уровня предполагается, что каждый по умолчанию получает роль самого низкого уровня, графически изображенную следующим образом:
role.Everyone //lowest level; everyone gets this role
role.Applications // everyone assigned this role gets applications && everyone roles
role.Databases // everyone assigned this role gets databases && applications && everyone roles
role.SoftwareSubscriber
role.Client_All // etc.
role.Client
role.ITClient
role.Client
role.NewsService // everyone assigned this role gets NewsService && Client && Everyone
// && Client_All roles, since Client is also a child of Client_All
role.ClientDeliverable // etc.
role.Employee
role.Corporate
role.Marketing
role...
...
Я бы хотел вернуть всех «родителей» (на самом деле, детей, но неважно) и их рекурсивных родителей на любую роль. Например, я ожидаю, что запрос, который запрашивает у родителей role.Databases
, возвращает role.Applications
и role.Everyone
. Точно так же я ожидаю, что запрос, который запрашивает у родителей role.NewsService
, возвращает role.Client
, role.Everyone
и role.Client_All
, поскольку role.Client
является потомком role.Everyone
и role.Client_All
.
Я попытался смоделировать запрос следующим образом после примера CTE MSDN , но я не могу найти всех рекурсивных родителей. Кто-нибудь может направить мой запрос CTE в правильном направлении?
CREATE TABLE #ATTRIBASSIGN
(
ATTRIBID int not null
, ITEMID int not null
, ITEMCLASS VARCHAR(10) NOT NULL DEFAULT ('ATTRIB')
, CONSTRAINT PK_ATTRIBASSIGN_ATTRIBID_ITEMID_ITEMCLASS PRIMARY KEY (ATTRIBID, ITEMID, ITEMCLASS)
)
CREATE TABLE #ATTRIBPROP
(
ATTRIBID int not null identity(1,1) primary key
, ATTRIBNAME VARCHAR(50) not null
)
GO
INSERT INTO #ATTRIBPROP (ATTRIBNAME)
VALUES ('role.Databases'), ('role.Applications'), ('role.Everyone'), ('role.Client_All'), ('role.Employee'), ('role.SoftwareSubscriber'),
('role.Client'), ('role.ITClient'), ('role.NewsService'), ('role.ClientDeliverable'), ('role.Corporate'), ('role.Marketing')
GO
INSERT INTO #ATTRIBASSIGN (ATTRIBID, ITEMID)
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Everyone'
AND B.ATTRIBNAME = 'role.Applications'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Everyone'
AND B.ATTRIBNAME = 'role.Client_All'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Everyone'
AND B.ATTRIBNAME = 'role.Client'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Everyone'
AND B.ATTRIBNAME = 'role.Employee'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Applications'
AND B.ATTRIBNAME = 'role.Databases'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Applications'
AND B.ATTRIBNAME = 'role.SoftwareSubscriber'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Client_All'
AND B.ATTRIBNAME = 'role.Client'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Client_All'
AND B.ATTRIBNAME = 'role.ITClient'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Client'
AND B.ATTRIBNAME = 'role.NewsService'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Client'
AND B.ATTRIBNAME = 'role.ClientDeliverable'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Employee'
AND B.ATTRIBNAME = 'role.Corporate'
UNION
SELECT A.ATTRIBID, B.ATTRIBID
FROM #ATTRIBPROP A
CROSS JOIN #ATTRIBPROP B
WHERE A.ATTRIBNAME = 'role.Employee'
AND B.ATTRIBNAME = 'role.Marketing'
GO
WITH RoleStructure (parentRole, currentRole, Level)
AS
(
SELECT B.ITEMID, B.ATTRIBID, 0 level
FROM #ATTRIBASSIGN B
WHERE B.ATTRIBID NOT IN
(
SELECT ITEMID
FROM #ATTRIBASSIGN C
WHERE B.ATTRIBID = C.ITEMID
)
AND B.ITEMCLASS = 'attrib'
UNION ALL
SELECT B.ITEMID, B.ATTRIBID, D.level - 1
FROM #ATTRIBASSIGN B
INNER JOIN RoleStructure D ON B.ATTRIBID = D.parentRole
WHERE B.ITEMCLASS = 'attrib'
)
SELECT B.ATTRIBNAME, C.ATTRIBNAME, level
FROM RoleStructure A
INNER JOIN #ATTRIBPROP B ON A.parentRole = B.ATTRIBID
INNER JOIN #ATTRIBPROP C ON A.currentRole = C.ATTRIBID