Recursive CTE Multiple Levels [duplicate]
-
10-03-2021 - |
Question
I have a table showing which roles recursively grant access to which resources within a database. For example:
The Default_Role grants access to the App_Role, the App_Role grants access to the Security_Role, and the Security_Role grants access to three tables (customers, sales, users). So a member of the Default_Role is granted all of these, but Default_Role is not granted access to the Sys_Role, and is not granted access to the System or Admin tables.
CREATE TABLE SQLTest(
DBName NVARCHAR(100) NULL
,Privilege NVARCHAR(100) NULL
,PrivilegeType NVARCHAR(100) NULL
,PrivilegeDetail NVARCHAR(100) NULL
,TableName NVARCHAR(100) NULL
)
INSERT INTO SQLTest
VALUES
('TSDB','Default_Role','Role','App_Role',NULL),
('TSDB','App_Role','Role','Security_Role',NULL),
('TSDB','Sys_Role','Role','Security_Role',NULL),
('TSDB','Security_Role','Table','Customers','Customers'),
('TSDB','Security_Role','Table','Sales','Sales'),
('TSDB','Security_Role','Table','Users','Users'),
('TSDB','Sys_Role','Table','System','System'),
('TSDB','Sys_Role','Table','Admin','Admin')
What is the best way to flatten this out so you can see all the access (roles and tables) granted to the Default_Role, without showing additional access not granted to the Default_Role? Like this:
Tried putting together this example, but doesn't work.
Solution
As CTE's are for the first test quite difficult to understand, i wrote a approach, with all Levels at the end
The Option at the end is nit needed, but to reduce espeically when you are trying to figure out what happens, you shoukld add it at a low number
WITH MyTest as
(
SELECT P.DBName, P.Privilege,p.PrivilegeType,P.PrivilegeDetail,P.TableName , CAST(P.PrivilegeDetail AS VarChar(Max)) as Level
FROM SQLTest P
WHERE P.Privilege = 'Default_Role'
UNION ALL
SELECT P1.DBName, P1.Privilege,p1.PrivilegeType,P1.PrivilegeDetail,p1.TableName , CAST(P1.PrivilegeDetail AS VarChar(Max)) + ', ' + M.Level
FROM SQLTest P1
INNER JOIN MyTest M
ON M.PrivilegeDetail = P1.Privilege
)
SELECT * From MyTest
OPTION (MAXRECURSION 50);
REsult
DBName Privilege PrivilegeType PrivilegeDetail TableName Level
TSDB Default_Role Role App_Role (null) App_Role
TSDB App_Role Role Security_Role (null) Security_Role, App_Role
TSDB Security_Role Table Customers Customers Customers, Security_Role, App_Role
TSDB Security_Role Table Sales Sales Sales, Security_Role, App_Role
TSDB Security_Role Table Users Users Users, Security_Role, App_Role