SQL Server 2005 introduced FOR XML, including FOR XML PATH. One nice side benefit is that there was a quirk in the way they did it which you could take advantage of to create a delimited list pretty easily:
with records as
(
select
User_name(role_principal_id) as Role,
user_name(member_principal_id) as Principal
from
sys.database_role_members
)
select distinct
r1.Principal,
stuff((select (', ' + Role)
from records r2
where r2.Principal = r1.Principal
order by Role
for xml path ( '' )
), 1, 1, '') as Roles
from
records r1
order by
r1.Principal
I'm using your query as the first part of a common table expression. Then, the trick is in the substring: using For XML Path the way I am here creates a set of all (', ' + Role) values--in other words, a comma-delimited list with roles. You take off the first two characters to get rid of the first ', '. Finally, you need a distinct because it will do this for every role in your set, whereas you just want to see it once per principal.
**Edit**: Replaced SUBSTRING with STUFF as per @Pavel Pawlowski's good point.
↧