这是报告XML的首要部分:
<Report xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner" xmlns:cl="http://schemas.microsoft.com/sqlserver/reporting/2010/01/componentdefinition" xmlns="http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition">
<AutoRefresh>0</AutoRefresh>
<DataSources>
<DataSource Name="DataSource1">
<DataSourceReference>Live Data</DataSourceReference>
<rd:SecurityType>None</rd:SecurityType>
<rd:DataSourceID>827954ef-81fc-4a34-8f40-5354265d867b</rd:DataSourceID>
</DataSource>
</DataSources>
</Report>
我要做的是获取DataSources的所有实例。经过几个小时的战斗,我意识到我必须使用多个命名空间并在我的select语句之前引用它们。这是我现在的询问:
;WITH XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition' AS ns, 'http://schemas.microsoft.com/sqlserver/reporting/2010/01/componentdefinition' AS cl, 'http://schemas.microsoft.com/SQLServer/reporting/reportdesigner' AS rd)
SELECT
c.*,
CAST( CONVERT(VARBINARY(MAX), c.Content) AS XML),
G.value('ns:DataSource[1]/rd:SecurityType[1]', 'NVARCHAR(MAX)') AS 'SecurityType',
G.value('ns:DataSource[1]/ns:DataSourceReference[1]', 'NVARCHAR(MAX)') AS 'DataSourceReference',
G.value('ns:DataSource[1]/rd:DataSourceID[1]', 'NVARCHAR(MAX)') AS 'DataSourceID'
FROM Catalog c
OUTER APPLY (SELECT CAST( CONVERT(VARBINARY(MAX), c.Content) AS XML)) as Content(c)
OUTER APPLY Content.c.nodes('//ns:DataSources') AS DS(G)
WHERE c.Type NOT IN (5, 4)
现在我非常困惑,因为它只适用于少量XML。我知道有另一种方法来提取该信息(我相信使用local-name()
)但我不仅希望它(无论如何可能)使它工作,而且还要理解为什么它不能以当前的形式工作(如果它不只是缺乏知识,而是SQL / XML克制。)
- 编辑:我使用OUTER APPLY获取所有不起作用的NULL,一旦我知道查询是现场,我会将其更改为CROSS
为了进行比较,这是XML的开头,查询返回正确的值:
<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">
<DataSources>
<DataSource Name="DataSource1">
<DataSourceReference>Live Data</DataSourceReference>
<rd:SecurityType>None</rd:SecurityType>
<rd:DataSourceID>956f67a3-7d7b-46cd-acb2-0e6490d0d33a</rd:DataSourceID>
</DataSource>
</DataSources>
我会永远感激任何帮助理解上述问题。
PS。我讨厌SQL中的XML!
答案 0 :(得分:1)
XML中的默认名称空间URI是:
xmlns="http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition"
在查询开始时,您有一个不同的URI映射到前缀ns
:
'http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition' AS ns
这可能是问题所在。如果您在不同的XML文档中有不同的命名空间,则无法避免使用local-name()
忽略命名空间,例如:
;WITH XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/reporting/2010/01/componentdefinition' AS cl, 'http://schemas.microsoft.com/SQLServer/reporting/reportdesigner' AS rd)
SELECT
c.*,
CAST( CONVERT(VARBINARY(MAX), c.Content) AS XML),
G.value('*[local-name()="DataSource"][1]/rd:SecurityType[1]', 'NVARCHAR(MAX)') AS 'SecurityType',
G.value('*[local-name()="DataSource"][1]/*[local-name()="DataSourceReference"][1]', 'NVARCHAR(MAX)') AS 'DataSourceReference',
G.value('*[local-name()="DataSource"][1]/rd:DataSourceID[1]', 'NVARCHAR(MAX)') AS 'DataSourceID'
FROM Catalog c
OUTER APPLY (SELECT CAST( CONVERT(VARBINARY(MAX), c.Content) AS XML)) as Content(c)
OUTER APPLY Content.c.nodes('//*[local-name()="DataSources"]') AS DS(G)
WHERE c.Type NOT IN (5, 4)