SSRS: How to find which reports have subreports? - sql-server

I have a lot of SQL Server Reporting Services (SSRS) reports (*.rdl). I want to know which of these reports are using subreports. How can I do that? Looking at an easier way instead of opening each report and figuring out if a subreport is being used.
Thanks

I think this should provide you with what you need (With thanks to Bret Stateham ):
--The first CTE gets the content as a varbinary(max)
--as well as the other important columns for all reports,
--data sources and shared datasets.
WITH ItemContentBinaries AS
(
SELECT
ItemID,Name,[Type]
,CASE Type
WHEN 2 THEN 'Report'
WHEN 5 THEN 'Data Source'
WHEN 7 THEN 'Report Part'
WHEN 8 THEN 'Shared Dataset'
ELSE 'Other'
END AS TypeDescription
,CONVERT(varbinary(max),Content) AS Content
FROM ReportServer.dbo.Catalog
WHERE Type IN (2,5,7,8)
),
--The second CTE strips off the BOM if it exists...
ItemContentNoBOM AS
(
SELECT
ItemID,Name,[Type],TypeDescription
,CASE
WHEN LEFT(Content,3) = 0xEFBBBF
THEN CONVERT(varbinary(max),SUBSTRING(Content,4,LEN(Content)))
ELSE
Content
END AS Content
FROM ItemContentBinaries
)
--The outer query gets the content in its varbinary, varchar and xml representations...
,VarcharContent as
(
SELECT
ItemID,Name,[Type],TypeDescription
,Content --varbinary
,CONVERT(varchar(max),Content) AS ContentVarchar --varchar
,CONVERT(xml,Content) AS ContentXML --xml
FROM ItemContentNoBOM
)
SELECT * FROM VarcharContent where ContentVarchar like '%<subreport%'

The following query below will return a list of deployed reports that have subreports. Here's the Microsoft reference and a link for referencing older versions of SSRS. It looks like the only difference is changing the version of SSRS in XMLNAMESPACES part of the CTE.
Query to return all subreports
WITH
XMLNAMESPACES
(
'http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition' AS rdl
)
,
report_list
AS
(
SELECT
[ReportID] = cat.[ItemID]
, [ReportName] = cat.[Name]
, [ReportPath] = cat.[Path]
, [xmlColumn] = CAST(CAST(cat.[Content] AS VARBINARY(MAX)) AS XML)
FROM
[ReportServer].[dbo].[Catalog] AS cat
WHERE
1=1
AND cat.[Content] IS NOT NULL
AND cat.[Type] = 2
)
SELECT
rpt.[ReportID]
, rpt.[ReportName]
, rpt.[ReportPath]
, [SubReportName] = srpt.x.value('(//rdl:ReportName)[1]', 'NVARCHAR(256)')
FROM
report_list AS rpt
CROSS APPLY xmlColumn.nodes('//rdl:Subreport') AS srpt(x);

Related

How to generate an excel file (.xlsx) from SQL Server

I have this query:
WITH InfoNeg AS
(
SELECT DISTINCT
n.idcliente,
CASE
WHEN DATEDIFF(MONTH, MAX(n.fechanegociacion), GETDATE()) <= 2
THEN 'Negociado 6 meses'
ELSE NULL
END AS TipoNeg
FROM
SAB2NewExports.dbo.negociaciones AS n
WHERE
Aprobacion = 'Si'
AND cerrado = 'Si'
GROUP BY
n.idcliente
), Multi AS
(
SELECT DISTINCT
idcliente, COUNT(distinct idportafolio) AS NumPorts
FROM
orangerefi.wfm.wf_master_HIST
WHERE
YEAR(Fecha_BKP) = 2021
AND MONTH(Fecha_BKP) = 08
GROUP BY
idcliente
)
SELECT DISTINCT
m.IdCliente, c.Nombre1
FROM
orangerefi.wfm.wf_master_HIST as m
LEFT JOIN
InfoNeg ON m.idcliente = InfoNeg.idcliente
LEFT JOIN
Multi ON m.IdCliente = Multi.idcliente
LEFT JOIN
SAB2NewExports.dbo.Clientes AS c ON m.IdCliente = c.IdCliente
WHERE
CanalTrabajo = 'Callcenter - Outbound' -- Cambiar aca
AND YEAR (Fecha_BKP) = 2021
AND MONTH(Fecha_BKP) = 08
AND GrupoTrabajo IN ('Alto') -- Cambiar aca
AND Bucket IN (1, 2) -- Cambiar aca
AND Multi.NumPorts > 1
AND Infoneg.TipoNeg IS NULL
When I run it, I get 30 thousand rows and the columns that I get when performing the query are: ClientID, name. I would like it to be saved in an Excel file when I run it, I don't know if it's possible.
Another question, is it possible to create a variable that stores text?
I used CONCAT(), but the text being so long is a bit cumbersome, I don't know if there is any alternative.
If you can help me, I appreciate it.
To declare a variable
DECLARE #string VARCHAR(MAX)
SET #string = concat()
then insert whatever you are concatenating
Here is an answer given by carusyte
Export SQL query data to Excel
I don't know if this is what you're looking for, but you can export the results to Excel like this:
In the results pane, click the top-left cell to highlight all the records, and then right-click the top-left cell and click "Save Results As". One of the export options is CSV.
You might give this a shot too:
INSERT INTO OPENROWSET
('Microsoft.Jet.OLEDB.4.0',
'Excel 8.0;Database=c:\Test.xls;','SELECT productid, price FROM dbo.product')
Lastly, you can look into using SSIS (replaced DTS) for data exports. Here is a link to a tutorial:
http://www.accelebrate.com/sql_training/ssis_2008_tutorial.htm
== Update #1 ==
To save the result as CSV file with column headers, one can follow the steps shown below:
Go to Tools->Options
Query Results->SQL Server->Results to Grid
Check “Include column headers when copying or saving results”
Click OK.
Note that the new settings won’t affect any existing Query tabs — you’ll need to open new ones and/or restart SSMS.

SQL Alternative for FOR XML PATH

For some reason my query :
SELECT
MP_SQLQRY_ProjectArchive.ProjectShort,
MP_SQLQRY_ProjectArchive.ProjectName ,
MP_SQLQRY_ProjectArchive.ProjectManagerName ,
ProjectOwnerName,
ProjStateName,
ProjectKategoryShort,
ProjectTypeShort,
MP_SQLQRY_ProjectArchive.ProjectPriority,
DepartmentShort,
ProjectArchivedDate,
CONVERT(NVARCHAR(MAX),ERPAccountCodes.ERPAccountCodes) As ERPAccountCodes
FROM
MP_SQLQRY_ProjectArchive
INNER JOIN
SQLQRY_VALID_PROJECT_ORDER_INFO ON MP_SQLQRY_ProjectArchive.ProjectID = SQLQRY_VALID_PROJECT_ORDER_INFO.ProjectID
INNER JOIN
COM_tbl_MAD_Project ON MP_SQLQRY_ProjectArchive.ProjectID = COM_tbl_MAD_Project.ProjectID
LEFT JOIN
(SELECT
ProjectID,
CONVERT(Nvarchar(max), STUFF((SELECT ';' + [SAPNumber] AS [data()]
FROM [COM_tbl_MAD_ProjectERPAccountCode] t2
WHERE t2.[ProjectID] = t1.[ProjectID]
ORDER BY [SAPNumber]
FOR XML PATH('')), 1, 1, '')) AS ERPAccountCodes
FROM
[COM_tbl_MAD_ProjectERPAccountCode] t1
GROUP BY
[ProjectID], [SAPNumber]) AS ERPAccountCodes ON ERPAccountCodes.ProjectID = COM_tbl_MAD_Project.ProjectID
will not return the values for the ERPAccountCodes column. In SQL Server, it works fine and I get my values, which are seperated with a ; as I want.
But when I run it as extern connection with ADODB in access this single column is empty.
I suppose it is a problem with access or ADODB but I have no clue what to do about it
Is there an alternative to FOR XML PATH or is there a different way to do it?
For clarification, the values return some blank values. Not NULL, just these weird blank symbols when i debugged in VBA in access, altough I tried converting it into a NVarchar which theoretically should work just fine.
Left is an Excel created from the MS Access SQL call. Right is from SQL Server Management Studio:

SQL Server output as XML all on one line

I'm using SQL Server 2014 and I'm new to XML. I'm trying to export 3 tables into XML. The 3 tables are:
Property (Parent)
PropertyArea (Child)
PropertyNotes (Child)
In SQL world, there is a left join from:
Property > PropertyArea
Property > PropertyNotes
The primary and foreign key is [property_id]
I have the below SQL code. However, when I open it in Notepad ++ it just creates the XML all on one line, and I was expecting to see it formatted.
DECLARE #XMLOutput XML
DECLARE #XMLOutputChar nvarchar(max)
;WITH XMLNAMESPACES('MyNameSpace' as ns)
SELECT #XMLOutput =
(
SELECT ISNULL(T1.[propertyusercode],'')AS propertyusercode,
ISNULL(T1.[NAME],'')AS [NAME],
(
SELECT
(
SELECT
[AreaCode]
,[AreaDesc]
FROM [PropertyArea]
WHERE [Property_Id] = T1.property_id
FOR XML PATH('Area'), TYPE
)
FOR XML PATH('Area'), TYPE
),
(
SELECT
(
SELECT
[NotesModuleNumber]
,[NotesPageNumber]
,[NotesText]
FROM [PropertyNotes]
WHERE [Property_Id] = T1.property_id
FOR XML PATH('Notes'), TYPE
)
FOR XML PATH('Notes'), TYPE
)
FROM Property T1
FOR XML PATH('Property'),TYPE, ROOT('Loader'),ELEMENTS XSINIL
)
SET #XMLOutputChar = '<?xml version="1.0" encoding="UTF-8"?>' + CONVERT(nvarchar(max),#XMLOutput)
SELECT #XMLOutputChar AS XMLOutput
Am I missing something? Is my code correct?
If you just want to see it on Notepad++, use plugin XML Tools to "pretty print" the XML into an easier to read format.
Copy paste from SQL Server:
After formatting:

Using T-SQL find the Stored Procedure associated to an SSRS Report

I had some help writing this query -- I'm at a bit of a loss because i'm trying to find the the query type or procedure used and i'm not sure what else to add to the query or how to change it.
SELECT
Ds.Name as Data_Source_Name,
C2.Name AS Data_Source_Reference_Name,
C.Name AS Dependent_Item_Name,
C.Path AS Dependent_Item_Path,
ds.*
FROM
ReportServer.dbo.DataSource AS DS
INNER JOIN
ReportServer.dbo.Catalog AS C ON DS.ItemID = C.ItemID
AND DS.Link IN (SELECT ItemID
FROM ReportServer.dbo.Catalog
WHERE Type = 5) --Type 5 identifies data sources
FULL OUTER JOIN
ReportServer.dbo.Catalog C2 ON DS.Link = C2.ItemID
WHERE
C2.Type = 5
AND c.name LIKE '%mkt%'
ORDER BY
C.Path, C2.Name ASC, C.Name ASC;
Please advise.
Based on my comment, give this a try, should get you moving in the right direction on how you can parse the xml and zero in on the specific command.
You might have to update the name spaces in the script below and also add your report name.
But try something like this:
;WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition') --You may have to change this based on you SSRS version
SELECT
[Path],
Name,
report_xml.value( '(/Report/DataSources/DataSource/#Name)[1]', 'VARCHAR(50)' ) AS DataSource,
report_xml.value( '(/Report/DataSets/DataSet/Query/CommandText/text())[1]', 'VARCHAR(MAX)' ) AS CommandText,
report_xml.value( '(/Report/DataSets/DataSet/Query/CommandType/text())[1]', 'VARCHAR(100)' ) AS CommandType,
report_xml
FROM
(
SELECT
[Path],
Name,
[Type],
CAST( CAST( content AS VARBINARY(MAX) ) AS XML ) report_xml
FROM dbo.[Catalog]
WHERE Content IS NOT NULL
AND [Type] = 2
) x
WHERE
--use below in where clause if searching for the CommandText. Depending on how the report was developed I would just use the proc name and no brackets or schema.
--Example: if you report was developed as having [dbo].[procName] just use LIKE '%procName%' below. Because other reports could just have dbo.procName.
report_xml.value( '(/Report/DataSets/DataSet/Query/CommandText/text())[1]', 'VARCHAR(MAX)' ) LIKE '%Your Proc Name here%'
--comment out the above and uncomment below if know your report name and want to search for that specific report.
--[x].[Name] = 'The Name Of Your Report'
You're in the right neighborhood... When a report RDL is published its XML is converted into a image data type and stored in dbo.Catalog.Content.
If you convert the image data to VARBINARY(MAX) and then convert to XML, you'll be able to read the XML in plain text.
SELECT TOP (10)
*
FROM
dbo.Catalog c
CROSS APPLY ( VALUES (CONVERT(XML, CONVERT(VARBINARY(MAX), c.Content))) ) cx (content_xml)
WHERE
c.Type = 2;
From there it's just a matter of parsing the XML to dig out what you're looking for. In this case you looking for tags that look like the following...
<DataSet Name="My_stored_proc">
Are you looking for the stored procedure name? If your looking to see where that is at its in the database itself, database > DatabaseName > Programmability > Stored Procedures. If your trying to use the query you built for a report you need to make the stored procedure or change the query type to text and paste it in the box.

Is it possible to Parse this XML file using SQL Server or SSIS?

I have an XML file I receive from a financial data provider called MDM. It shows which dividends I have downloaded. It includes information like Dividend rate, date and the security requested.
I have tried to parse this with SSIS using the XML source and Merge Join. I also tried SQL Server 2012 using Open XML and couldn't do it. I gathered these techniques from Youtube, google and searching this board. My goal is for this to be in an easy to read table format so I can see which securities received dividend information.
When I tried to Parse it with SSIS the following output names were given
FIELD
SECURITY
APP_PARAM
MDM_MESSAGE
The XML file is too big to post entirely here but I have included a Dropbox link that hopefully works. Hopefully someone can help. I am not sure if this file, though XML can be parsed or not.
https://dl.dropboxusercontent.com/u/29851290/parse_file.xml
Ideally the output will be something like this.
SYM_TYPE_ID SEC_SYMBOL SEC_TYPE_ID FOR DATE EX_DT PAY_DT WASH_AMOUNT RATE TICKER
aapl csus (Not sure) 5/15/2013 6/1/2013 (Not Sure) 0.25
Try this one -
DECLARE #XML XML
SELECT #XML = CONVERT (XML, [BulkColumn])
FROM OPENROWSET (BULK N'C:\parse_file.xml', SINGLE_BLOB) [XmlData]
SELECT PROV_ID = t.c.value('../#PROV_ID', 'VARCHAR(25)')
, SYM_TYPE_ID = t.c.value('../#SYM_TYPE_ID', 'VARCHAR(25)')
, SEC_SYMBOL = t.c.value('../#SEC_SYMBOL', 'VARCHAR(25)')
, SEC_TYPE_ID = t.c.value('../#SEC_TYPE_ID', 'VARCHAR(25)')
, LOCAL_NAME = t.c.value('#LOCAL_NAME', 'VARCHAR(25)')
, FOR_DATE = t.c.value('#FOR_DATE', 'DATETIME')
, FIELD = t.c.value('.', 'VARCHAR(25)')
FROM #XML.nodes('root/MDM_MESSAGE[2]/SECURITY/FIELD') t(c)
WHERE t.c.value('#SEC_SYMBOL', 'VARCHAR(25)') = '57636Q104'
UNION ALL
SELECT PROV_ID = t.c.value('#PROV_ID', 'VARCHAR(25)')
, SYM_TYPE_ID = t.c.value('#SYM_TYPE_ID', 'VARCHAR(25)')
, SEC_SYMBOL = t.c.value('#SEC_SYMBOL', 'VARCHAR(25)')
, SEC_TYPE_ID = t.c.value('#SEC_TYPE_ID', 'VARCHAR(25)')
, LOCAL_NAME = NULL
, FOR_DATE = NULL
, FIELD = NULL
FROM #XML.nodes('root/MDM_MESSAGE[2]/SECURITY') t(c)
WHERE t.c.exist('FIELD') = 0
AND t.c.value('#SEC_SYMBOL', 'VARCHAR(25)') = '57636Q104'

Resources