我有一个名为 Audit.Event 的表来捕获用户事件,该表中的一列将数据存储为xml,其结构如此
XML数据
<OrganisationSearchEvent xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Options>
<IsAgency>false</IsAgency>
<IsCharity>false</IsCharity>
<IsCompany>false</IsCompany>
<IsEducationalEstablishment>false</IsEducationalEstablishment>
<IsProgrammeProvider>false</IsProgrammeProvider>
<Name i:nil="true" />
<OrganisationIDs xmlns:d3p1="http://schemas.datacontract.org/2004/07/System" i:nil="true" />
<ProfessionalBodies xmlns:d3p1="http://schemas.datacontract.org/2004/07/System" i:nil="true" />
<Sectors xmlns:d3p1="http://schemas.datacontract.org/2004/07/System">
<d3p1:int>21</d3p1:int>
<d3p1:int>82</d3p1:int>
</Sectors>
<SubSector xmlns:d3p1="http://schemas.datacontract.org/2004/07/System" i:nil="true" />
</Options>
<Paging>
<EndRecord i:nil="true" />
<PageNumber>1</PageNumber>
<PagingMode>Paged</PagingMode>
<RecordsPerPage>20</RecordsPerPage>
<StartRecord i:nil="true" />
<TotalPages>1</TotalPages>
</Paging>
</OrganisationSearchEvent>
我需要粉碎xml并捕获名为 d3p1:int 的元素中的数据。到目前为止,我已经写了以下查询:
查询
SELECT
Data.value('(//d3p1:int)[1]', 'int') AS [SectorID],
FROM [Audit].[EventData]
Cross Apply Data.nodes('//OrganisationSearchEvent/Options/Sectors') as Test(X)
Where EventTypeID = 7
Order By CapturedDateTime Desc
我希望看到的只是
+----------+
| SectorID |
+----------+
| 10 |
| 45 |
| 50 |
| 22 |
| 6 |
+----------+
但我得到以下错误
名称“d3p1”不表示命名空间。
如果我用“d3p1”替换“d3p1:int”,则返回空值
如果我在select子句中使用以下行作为测试,则返回该元素的正确数据。
Data.value('(//Name)[1]','nvarchar(100)') AS [Name]
有人能指出我正确的方向,我不确定这是什么原因
由于
根据Shnugo的建议,我尝试了以下但没有运气,我一定错过了什么!
我无法指向显示的实际XML数据,因为这是通过应用程序存储到“Autit.EventData”表中的一列中,我试图做的就是这个。
尝试1
Declare @xml XML=[Audit].[EventData].[Data]
;WITH XMLNAMESPACES ('http://www.w3.org/2001/XMLSchema-instance' AS d3p1)
SELECT i.value('.','int') AS [SectorID]
FROM @xml.nodes('/OrganisationSearchEvent/Options/Sectors/d3p1:int') as A(i)
但是我收到了错误
无法绑定多部分标识符“Audit.EventData.Data”。
我假设我仍然需要使用该表,所以我接下来尝试了这个
尝试2
;WITH XMLNAMESPACES ('http://www.w3.org/2001/XMLSchema-instance' AS d3p1)
SELECT i.value('.','int') AS [SectorID]
FROM [Audit].[EventData]
Cross Apply Data.nodes('/OrganisationSearchEvent/Options/Sectors/d3p1:int') as A(i)
但这不会返回任何内容
最终解决方案
这是我用来返回正确数据的最终查询
SELECT
T.C.value('.', 'int') as [SelectedID's]
from Audit.[EventData]
cross apply Data.nodes('/OrganisationSearchEvent/Options/Sectors/*') as T(C)
where EventTypeID = 7
order by CapturedDateTime desc
答案 0 :(得分:3)
试试这样:
DECLARE @xml XML=
'<OrganisationSearchEvent xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Options>
<IsAgency>false</IsAgency>
<IsCharity>false</IsCharity>
<IsCompany>false</IsCompany>
<IsEducationalEstablishment>false</IsEducationalEstablishment>
<IsProgrammeProvider>false</IsProgrammeProvider>
<Name i:nil="true" />
<OrganisationIDs xmlns:d3p1="http://schemas.datacontract.org/2004/07/System" i:nil="true" />
<ProfessionalBodies xmlns:d3p1="http://schemas.datacontract.org/2004/07/System" i:nil="true" />
<Sectors xmlns:d3p1="http://schemas.datacontract.org/2004/07/System">
<d3p1:int>21</d3p1:int>
<d3p1:int>82</d3p1:int>
</Sectors>
<SubSector xmlns:d3p1="http://schemas.datacontract.org/2004/07/System" i:nil="true" />
</Options>
<Paging>
<EndRecord i:nil="true" />
<PageNumber>1</PageNumber>
<PagingMode>Paged</PagingMode>
<RecordsPerPage>20</RecordsPerPage>
<StartRecord i:nil="true" />
<TotalPages>1</TotalPages>
</Paging>
</OrganisationSearchEvent>';
WITH XMLNAMESPACES('http://schemas.datacontract.org/2004/07/System' AS d3p1)
SELECT i.value('.','int')
FROM @xml.nodes('//d3p1:int') AS A(i);
如果没有名称空间,您可以使用像这里的通配符
SELECT i.value('.','int')
FROM @xml.nodes('//*:int') AS A(i);
甚至是完整路径
WITH XMLNAMESPACES('http://schemas.datacontract.org/2004/07/System' AS d3p1)
SELECT i.value('.','int')
FROM @xml.nodes('/OrganisationSearchEvent/Options/Sectors/d3p1:int') AS A(i);
这取决于您的要求。一般建议是:尽可能具体。
关于您的代码:如果您想阅读所有int-elements ,则需要.nodes()
来返回<d3p1:int>
- 元素。您的查询停止一级到高级。其次,如果必须处理命名空间,则必须明确使用它们或使用通配符。
在不知道您的实际数据库的情况下,很难指出您......
从我提出的问题来看,这是:
SELECT
Data.value('(//d3p1:int)[1]', 'int') AS [SectorID],
FROM [Audit].[EventData]
Cross Apply Data.nodes('//OrganisationSearchEvent/Options/Sectors') as Test(X)
Where EventTypeID = 7
Order By CapturedDateTime Desc
与此一起
Data.value('(//Name)[1]','nvarchar(100)') AS [Name]
返回正确的数据吗?
如果是这样,最不具体的方法可能是:
SELECT
Data.value('.','int') AS SectorID
FROM [Audit].[EventData]
Cross Apply Data.nodes('//*:int') as Test(X)
Where EventTypeID = 7
Order By CapturedDateTime Desc
这应该选择任何名为int
的元素(不是数据类型,元素的名称!)并列出 row-wise ......
如果你让它工作,你可能会尝试找到更具体的XPath
,但这应该 - 至少 - 返回正确的值......