I'm working on a query for SQL Server (2008 R2 at the moment) - my goal is to produce a result set that lists every report defined in SSRS under a specific path along with a grid that has a column for each uniquely named report parameter on the server, with the contents of the grid being a "checkmark" (e.g. non-null value) for each Report + Parameter combination for which the corresponding report has a parameter with the corresponding name. The query needs to be case sensitive on report parameter names - one purpose of the query is to identify reports that have parameters spelled with inconsistent casing.
I was able to write that query using a number of techniques (that some might call ugly hacks):
use ReportServer
go
declare @path nvarchar(255);
set @path = N'SSRS Path To Folder'
-- return a table with two columns: ReportName, ParameterName with one row for each
-- distinct ReportName + ParameterName combination
select
t.Name as ReportName,
pn.value collate Latin1_General_CS_AI as ParameterName
into
#rp
from
(
-- return a table with two columns: ReportName and ParameterNames (comma-separated list of
-- parameters in declaration order)
select
[Name],
(select STUFF((select ', ' + p.n.value('.', 'varchar(255)')
from ParameterXml.nodes('/Parameters/Parameter/Name') p(n)
for xml path('')), 1, 2, '')
) as ParameterNames
from
(
select
*,
CAST(Parameter as xml) as ParameterXml
from
[Catalog]
) c
where
[Path] like '/' + @path + '/%'
and [Type] = 2
) t
cross apply dbo.SplitString(t.ParameterNames) pn
-- Pivot the above result into a table with one row per report and one column for each
-- distinct report parameter name. Parameter-named columns contain a flag - 1 or null -
-- that indicates whether the report corresponding to that row defines the parameter
-- corresponding to that column.
create database CS_Temp collate Latin1_General_CS_AI;
go
use CS_Temp
go
declare @cols nvarchar(MAX), @query nvarchar(MAX);
set @cols = STUFF(
(
select
distinct ','+QUOTENAME(rp.ParameterName)
from
#rp rp
for xml path(''), type).value('.', 'nvarchar(max)'
),1,1,''
);
set @query = 'SELECT ReportName, ' + @cols + ' from
(
select ReportName, 1 as Used, ParameterName from #rp
) x
pivot
(
max(Used) for ParameterName in (' + @cols + ')
) p
';
execute(@query)
go
drop table #rp
use ReportServer;
go
drop database CS_Temp;
go
(SplitString function from Erland Sommarskog/Itzik Ben-Gan, dynamic pivot technique from Aaron Bertrand). This query does work, but it's slow and ugly - which is actually OK for my use case. What I'm wondering though, is if there's any better way to get the pivot to work with case sensitive column names than what I've done here: Actually creating a database with a case-sensitive collation, switching to that context and executing the pivot query. The database serves no purpose other than providing the collation for the database meta-data - i.e. column names in the result of the pivot query.