查询存储在SQL Server中的XML数据

时间:2017-04-07 15:16:14

标签: sql-server xml

我有一个名为Resume of XML的列存储在MS-SQL Server的表中。

我想找回所有来自萨吉诺市的候选人。

当我使用查询时

SELECT Resume.query('(: explicit namespace :)declare namespace ns="Namespace-Resume";
                //ns:Address/ns:Addr.Location/ns:Location/ns:Loc.City')
FROM JobCandidate

我获得了城市的所有值,但是当我使用以下查询时:

SELECT Resume.query('(: explicit namespace :)declare namespace ns="Namespace-Resume";
                //ns:Location[@ns:Loc.City="Saginaw"]/ns:Name')
FROM JobCandidate

我收到错误“没有名为Loc.City的属性”。

样本数据如下:

<ns:Resume xmlns:ns="Namespace-Resume">
<ns:Name>
    <ns:Name.Prefix></ns:Name.Prefix>
    <ns:Name.First>Shai</ns:Name.First>
    <ns:Name.Middle></ns:Name.Middle>
    <ns:Name.Last>Bassli</ns:Name.Last>
    <ns:Name.Suffix></ns:Name.Suffix>
  </ns:Name>
<ns:Address>
<ns:Addr.Type>Home</ns:Addr.Type>
<ns:Addr.Street>567 3rd Ave</ns:Addr.Street>
<ns:Addr.Location>
  <ns:Location>
    <ns:Loc.CountryRegion>US </ns:Loc.CountryRegion>
    <ns:Loc.State>MI </ns:Loc.State>
    <ns:Loc.City>Saginaw</ns:Loc.City>
  </ns:Location>
</ns:Addr.Location>
</ns:Address>
</ns:Resume>

1 个答案:

答案 0 :(得分:1)

你的问题并不是很清楚...我会提供几种方法,其中一种方法可以指明你的方式(你可以将整个批次复制到查询窗口并执行它独立):

DECLARE @xml XML=
N'<ns:Resume xmlns:ns="Namespace-Resume">
  <ns:Name>
    <ns:Name.Prefix />
    <ns:Name.First>Shai</ns:Name.First>
    <ns:Name.Middle />
    <ns:Name.Last>Bassli</ns:Name.Last>
    <ns:Name.Suffix />
  </ns:Name>
  <ns:Address>
    <ns:Addr.Type>Home</ns:Addr.Type>
    <ns:Addr.Street>567 3rd Ave</ns:Addr.Street>
    <ns:Addr.Location>
      <ns:Location>
        <ns:Loc.CountryRegion>US </ns:Loc.CountryRegion>
        <ns:Loc.State>MI </ns:Loc.State>
        <ns:Loc.City>Saginaw</ns:Loc.City>
      </ns:Location>
    </ns:Addr.Location>
  </ns:Address>
</ns:Resume>';

- 使用命名空间通配符

读取一个元素的文本
SELECT @xml.value(N'(/*:Resume/*:Name/*:Name.First/text())[1]',N'nvarchar(max)');

- 使用默认命名空间

WITH XMLNAMESPACES(DEFAULT N'Namespace-Resume')
SELECT @xml.value(N'(/Resume/Address/Addr.Location/Location/Loc.City/text())[1]',N'nvarchar(max)');

- 您的示例XML仅包含一个人,但我认为还有更多 - 使用谓词来获取给定位置的名称

DECLARE @location NVARCHAR(100)=N'Saginaw';--Change this for tests
WITH XMLNAMESPACES(DEFAULT N'Namespace-Resume')
SELECT @xml.value(N'(/Resume[(Address/Addr.Location/Location/Loc.City/text())[1]=sql:variable("@location")]/Name/Name.First/text())[1]',N'nvarchar(max)');

- 读取此节点的多个值 - 使用谓词来获取给定位置的名称

WITH XMLNAMESPACES(DEFAULT N'Namespace-Resume')
SELECT r.value(N'(Name/Name.First/text())[1]',N'nvarchar(max)')
      ,r.value(N'(Name/Name.Last/text())[1]',N'nvarchar(max)') 
FROM @xml.nodes(N'/Resume[(Address/Addr.Location/Location/Loc.City/text())[1]=sql:variable("@location")]') AS A(r);

更新:您在评论中提供的SELECT

缺少对nodes()的调用?试试这样:

DECLARE @location NVARCHAR(100)=N'Saginaw'; 
WITH XMLNAMESPACES(DEFAULT N'Namespace-Resume') 
SELECT r.value(N'(Name/Name.First/text())[1]',N'nvarchar(max)')
      ,r.value(N'(Name/Name.Last/text())[1]',N'nvarchar(max)') 
FROM JobCandidate
CROSS APPLY Resume.nodes(N'/Resume[(Address/Addr.Location/Location/Loc.City/text())[1]=sql:variable("@location")]') AS A(r);

更新2:根据您的评论命名空间

DECLARE @xml XML=
N'<ns:Resume xmlns:ns="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume">
  <ns:Name>
    <ns:Name.Prefix />
    <ns:Name.First>Shai</ns:Name.First>
    <ns:Name.Middle />
    <ns:Name.Last>Bassli</ns:Name.Last>
    <ns:Name.Suffix />
  </ns:Name>
  <ns:Address>
    <ns:Addr.Type>Home</ns:Addr.Type>
    <ns:Addr.Street>567 3rd Ave</ns:Addr.Street>
    <ns:Addr.Location>
      <ns:Location>
        <ns:Loc.CountryRegion>US </ns:Loc.CountryRegion>
        <ns:Loc.State>MI </ns:Loc.State>
        <ns:Loc.City>Saginaw</ns:Loc.City>
      </ns:Location>
    </ns:Addr.Location>
  </ns:Address>
</ns:Resume>';
DECLARE @location NVARCHAR(100)=N'Saginaw';--Change this for tests

WITH XMLNAMESPACES(DEFAULT N'http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume')
SELECT r.value(N'(Name/Name.First/text())[1]',N'nvarchar(max)')
      ,r.value(N'(Name/Name.Last/text())[1]',N'nvarchar(max)') 
FROM @xml.nodes(N'/Resume[(Address/Addr.Location/Location/Loc.City/text())[1]=sql:variable("@location")]') AS A(r);