设置多个 XMLNAMESPACES 以说明 SQL 查询中 SSRS/SQL 的不同版本

Set Multiple XMLNAMESPACES to account for different versions of SSRS/SQL in an SQL Query

我正在尝试查询 SSRS 报表服务器数据库,搜索使用 LIKE 语句使用特定存储过程的任何报表。

下面的代码完美运行:

WITH XMLNAMESPACES 
( DEFAULT 
  'http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition'
, 'http://schemas.microsoft.com/SQLServer/reporting/reportdesigner' AS ReportDefinition )
SELECT  
CATDATA.Name AS ReportName
,CATDATA.Path AS ReportPathLocation
,xmlcolumn.value('(@Name)[1]', 'VARCHAR(250)') AS DataSetName  
,xmlcolumn.value('(Query/DataSourceName)[1]','VARCHAR(250)') AS DataSoureName 
,xmlcolumn.value('(Query/CommandText)[1]','VARCHAR(2500)') AS CommandText
FROM (  
    SELECT C.Name
    ,C.Path
    ,CONVERT(XML,CONVERT(VARBINARY(MAX),C.Content)) AS reportXML
    FROM  ReportServer.dbo.Catalog C
    WHERE  C.Content is not null
    AND  C.Type = 2
    ) CATDATA
CROSS APPLY reportXML.nodes('/Report/DataSets/DataSet') xmltable ( xmlcolumn )
WHERE 
xmlcolumn.value('(Query/CommandText)[1]','VARCHAR(500)') LIKE '%sp_%'
ORDER BY CATDATA.Name

但是我想跨多个 XML 命名空间进行查询,以说明 SSRS/SQL 版本随时间的变化,以确保查询不会遗漏任何记录。

'http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition'
'http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition'

我仍然是 XML 的相对初学者,有什么想法或建议我会如何去做?

非常感谢

如果您不介意不同名称空间中的节点冲突,那么您可以完全忽略名称空间,使用 *:node

SELECT  
CATDATA.Name AS ReportName
,CATDATA.Path AS ReportPathLocation
,xmlcolumn.value('(@Name)[1]', 'VARCHAR(250)') AS DataSetName  
,xmlcolumn.value('(*:Query/*:DataSourceName/text())[1]','VARCHAR(250)') AS DataSoureName 
,xmlcolumn.value('(*:Query/*:CommandText/text())[1]','VARCHAR(2500)') AS CommandText
FROM (  
    SELECT C.Name
    ,C.Path
    ,CONVERT(XML,CONVERT(VARBINARY(MAX),C.Content)) AS reportXML
    FROM  ReportServer.dbo.Catalog C
    WHERE  C.Content is not null
    AND  C.Type = 2
    ) CATDATA
CROSS APPLY reportXML.nodes('/*:Report/*:DataSets/*:DataSet') xmltable ( xmlcolumn )
WHERE 
xmlcolumn.value('(*:Query/*:CommandText/text())[1]','VARCHAR(500)') LIKE '%sp_%'
ORDER BY CATDATA.Name

出于性能原因,您应该始终使用 /text() 获取节点的内部文本。

请注意,您可以将 WHERE 过滤器合并到 nodes 过滤器中,并直接在 XQuery 中进行:

CROSS APPLY reportXML.nodes(
    '/*:Report/*:DataSets/*:DataSet[
                             *:Query[*:CommandText[
                                   contains(text()[1], "sp_")
                   ]]]') xmltable ( xmlcolumn )