SQL Server 如何通过SQL语句定位SSRS中的具体报表

在一些IT技术人员的推广、简单培训后,公司很多部门都有一些非IT技术人员参与开发各自需求的Reporting Service报表。原因很简单,罗列出来的原因大概有这样一些:

 

IT部门的考量:

1:IT部门这边工作量很大,跟进各个项目都力不从心。不想腾出精力和时间来解决各个部门层出不穷的报表需求。

2:IT技术人员可能对各个部门的业务的理解和那些精通业务的员工有一定的差距。业务人员才是真正懂得应用需求的核心人员。

3:这些报表的需求变跟和后续维护实在是一个不小的工作量。IT的人手、资源实在有些不足。

4:这些零零散散的报表体现不了工作量,体现不了绩效。原因你懂的。

………………………………………………………………………………

 

业务部门考量:

1:公司各个部门确实需要各类报表,跟进生产进度、调整生产计划,作出相关决策。这个需求的的确确是刚性需求。而且有利于提高生效效率。

2:业务人员虽然精通业务,仅仅熟悉制作Excel报表。对IT技术不了解,但是经过培训、推广后,发现Reporting Service的报表确实开发简单、而且图文并茂,美观大方。最重要的是可以重复使用,而且可以订阅、推送,大大节省了他们制作报表的时间和工作量。所以学习制作报表的热情和激情高涨

3:他们提出的需求不能得到IT部门的快速响应。有时候一拖就是一天或者几天。而需求总是在变化,他们迫切希望自己掌控这些变化。

…………………………………………………………………………………………………………………………….

 

结果他们“郎有情妾有意”一拍即合,结果给我整出无数的琐碎事情:一来很多人申请Reporting Service的相关权限,很多人发布更新报表。事情倒不复杂,只是琐碎繁杂,烦不胜烦,只能将一些权限下放。这个问题解决了,但是随之而来的一个更大的问题,那些没有经过专业培训的业务人员写出的SQL实在是让人大跌眼镜。有时候严重影响数据库性能。我们通过监控工具能定位到是那个Reporting Service报表发出的问题SQL,但是要如何定位到具体的报表,这样才能找到报表的Owner,督促其修改、优化SQL。否则即使我们定位了问题SQL以及知道如何优化,但是不能修改对应的报表,也只能看着问题重演。如果只是简单的将SQL发给这么一大批人,让他们自己去甄别,刷选,这个沟通的成本太高,而且效率低下,效果非常差。

 

搜索了一些关于Reporting Service中报表的资料,我们知道Reporting Service报表的内容都保存在ReportServer这个数据库的dbo.Catalog表中,但是官方没有关于Catalog这些系统表的相关文档。仅仅是一些对SSRS感兴趣的人做了一些深入研究,相关资料如下

 

关于Type字段的值代表的意义:

1 = Folder

2 = Report

3 = Resources

4 = Linked Report

5 = Data Source

6 = Report Model

7 = Report Part (SQL 2008 R2, unverified)

8 = Shared Dataset (SQL 2008 R2)

 

报表的XML信息保存在Catalog的Content字段中,但是Content的数据类型为Image(这个相当纳闷,不清楚为什么是这样一个设计?),如下所示,我们可以做一个转换

 

我们在转换成XML的文本中就能找到对应的SQL,节点一般为为/Report/DataSets/DataSet/Query/CommandText如下截图所示:

 

 

将报表内容转换为XML后,需要从XML中模糊搜索才能定位SQL出自那张报表,如下所示

 

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 )
),
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
)
,ItemContentXML AS
(
  SELECT
     ItemID,Name,[Type],TypeDescription
    ,CONVERT(xml,Content) AS ContentXML
 FROM ItemContentNoBOM
)
SELECT
     ItemID,Name,[Type],TypeDescription,ContentXML
    ,ISNULL(Query.value('(./*:CommandType/text())[1]','nvarchar(1024)'),'Query') AS CommandType
    ,Query.value('(./*:CommandText/text())[1]','nvarchar(max)') AS CommandText
    
FROM ItemContentXML
CROSS APPLY ItemContentXML.ContentXML.nodes('//*:Query') Queries(Query)
WHERE Query.value('(./*:CommandText/text())[1]','nvarchar(max)') LIKE  '%SQL Script Content%';

 

不过这个SQL的性能实在慢的让人抓狂。如果有多个SQL需要定位,实在是一件折磨人的事情,我们可以将上面结果放入一张中间表或全局临时表,然后就可以快速、反复的定位SQL来自那种报表了。

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 )
),
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
)
,ItemContentXML AS
(
  SELECT
     ItemID,Name,[Type],TypeDescription
    ,CONVERT(xml,Content) AS ContentXML
 FROM ItemContentNoBOM
)
SELECT
     ItemID,Name,[Type],TypeDescription,ContentXML
    ,ISNULL(Query.value('(./*:CommandType/text())[1]','nvarchar(1024)'),'Query') AS CommandType
    ,Query.value('(./*:CommandText/text())[1]','nvarchar(max)') AS CommandText
INTO ##ReportContent
FROM ItemContentXML
CROSS APPLY ItemContentXML.ContentXML.nodes('//*:Query') Queries(Query);
 
SELECT * FROM ##ReportContent
WHERE  CommandText LIKE '%使用报表的部分SQL来替换%'

 

如下样例所示,已经知道报表的名字,以及报表ItemID,如果你想知道报表的详细路径,通过ItemID查询ReportServer.dbo.Catalog即可得到你想要的路径信息。

 

 

参考资料:

https://social.msdn.microsoft.com/Forums/sqlserver/en-US/60dd3392-42d8-4dc4-b8e6-15e9aeaad29e/table-explaination-for-dbocatalog-table-in-reportserver-database?forum=sqlreportingservices

http://bretstateham.com/extracting-ssrs-report-rdl-xml-from-the-reportserver-database/

 

时间: 2024-10-02 15:37:37

SQL Server 如何通过SQL语句定位SSRS中的具体报表的相关文章

[SQL Server]管理常用SQL语句

server|语句 [SQL Server]管理常用SQL语句 1. 查看数据库的版本        select @@version 2. 查看数据库所在机器操作系统参数        exec master..xp_msver 3. 查看数据库启动的参数         sp_configure 4. 查看数据库启动时间         select convert(varchar(30),login_time,120) from master..sysprocesses where spi

Microsoft SQL Server 2005数据库镜像语句

Microsoft SQL Server 2005数据库镜像语句: SERVER 1 CREATE ENDPOINT DbMirroring STATE=STARTED AS TCP(LISTENER_PORT=5023) FOR DATABASE_MIRRORING(ROLE=PARTNER,ENCRYPTION=SUPPORTED) ALTER DATABASE AdventureWorks SET PARTNER='TCP://192.168.5.106:5022' SERVER 2 CR

在SQL Server的try...catch语句中获取错误消息代码的的语句

本文为大家详细介绍下如何在SQL Server的try...catch语句中获取错误消息的代码,具体示例如下,感兴趣的朋友可以参考下哈,希望对大家有所帮助   复制代码 代码如下: BEGIN TRY ... ... END TRY BEGIN CATCH DECLARE @ErrorMessage NVARCHAR(4000); DECLARE @ErrorSeverity INT; DECLARE @ErrorState INT; SELECT @ErrorMessage = ERROR_M

【SQL SERVER 数据库实用SQL语句】

[SQL SERVER 数据库实用SQL语句] 1.按姓氏笔画排序: Select * From TableName Order By CustomerName Collate Chinese_PRC_Stroke_ci_as 2.分页SQL语句 select * from(select (row_number() OVER (ORDER BY tab.ID Desc)) as rownum,tab.* from 表名 As tab) As t where rownum between 起始位置

死锁问题-sql server 用这段语句,3个人一起点就容易死锁,有解决过的没有,如果解决的话,加分给你

问题描述 sql server 用这段语句,3个人一起点就容易死锁,有解决过的没有,如果解决的话,加分给你 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ BEGIN TRAN DECLARE @UserCode VARCHAR(20) SELECT TOP 1 @UserCode=usercode FROM dbo.tb_refUserCode With(RowLock,UpdLock) WHERE usestatus=0 --WHERE Use

sql server的across join语句怎么用?用它怎么取分组结果的第一条记录呢?

问题描述 sql server的across join语句怎么用?用它怎么取分组结果的第一条记录呢? sql server的across join语句怎么用?用它怎么取分组结果的第一条记录呢? 解决方案 http://www.2cto.com/database/201509/442742.html 解决方案二: http://zhidao.baidu.com/link?url=zu-YuSRPF-4RKb_yrqC7cZm4Smbz_pWS31ltTFn6HIknGbUHgcOtH8FavG9o

SQL Server版本号查看sql语句(SQL Server 2000 & 2005 & 2008)

今天要查询自己的装的sqlserver2008 是否是R2版本,搜索了下,发现很多人查询此问题,现在记录如下,通过版本命令查询 同时也了解了哥哥sql server的对应版本好,一看就非常清晰了,记录下 1.查看 SQL Server 2005/2008 版本号  代码如下 复制代码 select serverproperty('productversion') ,serverproperty('productlevel') ,serverproperty('edition') 下面是 SQL

关于SQL Server 2000和SQL Server 2005分布式事务能否协同工作的测试

server|分布式 关于SQL Server 2000和SQL Server 2005分布式事务能否协同工作的测试 MS DTC Report 1.      MS DTC 背景 2.      MSDTC 测试目的 3.      MSDTC 测试环境 3.1            本次验证测试环境: 3.2            环境配置 3.3            验证MSDTC 3.4            创建验证用表 4.      Linked Server测试 5.     

SQL Server执行动态SQL正确方式

SQL Server执行动态SQL的话,应该如何实现呢?下面就为您介绍SQL Server执行动态SQL两种正确方式,希望可以让您对SQL Server执行动态SQL有更深的了解. 动态SQL:code that is executed dynamically.它一般是根据用户输入或外部条件动态组合的SQL语句块.动态SQL能灵活的发挥SQL强大的功能.方便的解决一些其它方法难以解决的问题.相信使用过动态SQL的人都能体会到它带来的便利,然而动态SQL有时候在执行性能(效率)上面不如静态SQL,