【问题标题】:select multiple nodes xml选择多个节点xml
【发布时间】:2013-03-13 15:41:46
【问题描述】:

我正在从 ntext 字段中检索 xml 格式的文本(下面一行的示例格式):

<root>
  <DocInfo>
    <CompanyName>Some Company</CompanyName>
    <WebsiteUrl>http://www.someurl.com</WebsiteUrl>
    <PrimaryServices>Benefits Administration</PrimaryServices>
    <PrimaryServices>Payroll Processing</PrimaryServices>
    <SecondaryServices>Background Checking</SecondaryServices>
    <SecondaryServices>HR Outsourcing</SecondaryServices>
    <SecondaryServices>Comp & Benefits</SecondaryServices>
    <SecondaryServices>Administration</SecondaryServices>
  </DocInfo>
</root>

使用这个 sql 我正在检索单个节点值:

select  @xmlString = COALESCE(@xmlString + '', '') + cast(content_html as nvarchar(max)) FROM  content where folder_id = 18
set @xmlString = replace(@xmlString,'<?xml version="1.0" encoding="UTF-16" standalone="yes"?>','')
set @XML = cast(@xmlString as xml)

Select
T.N.value('CompanyName[1]', 'varchar(250)') as CompanyName,
T.N.value('WebsiteUrl[1]', 'varchar(250)') as WebsiteUrl,
T.N.value('PrimaryServices[1]', 'varchar(250)') as PrimaryServices,
T.N.value('SecondaryServices[1]', 'varchar(250)') as SecondaryServices,
T.N.value('Description[1]', 'varchar(max)') as Description
from @XML.nodes('/root/DocInfo') as T(N)

这适用于单个节点值(CompanyName、WebsiteUrl)。但是,它没有正确插入具有多个值的节点(例如 PrimaryServices 和 SecondaryServices - 每个节点可能有 0 到 16 个节点)。如何将这些可变长度的多个节点值放入这些列中?

感谢您的帮助

【问题讨论】:

    标签: sql-server xml sql-server-2008 xquery-sql


    【解决方案1】:

    要将多个节点作为逗号分隔值,您可以使用for xml path('') 技巧的变体。在子查询中使用粉碎的 XML (T.N) 作为源来获取您感兴趣的节点。xQuery ... substring(text()[1]) ... 部分只是用于删除额外的逗号并从 XML 中获取逗号分隔值由for xml创建。

    select
      T.N.value('(CompanyName/text())[1]', 'varchar(250)') as CompanyName,
      T.N.value('(WebsiteUrl/text())[1]', 'varchar(250)') as WebsiteUrl,
      (
        select ', '+P.N.value('text()[1]', 'varchar(max)')
        from T.N.nodes('PrimaryServices') as P(N)
        for xml path(''), type
      ).value('substring(text()[1], 2)', 'varchar(max)') as PrimaryServices,
      (
        select ', '+S.N.value('text()[1]', 'varchar(max)')
        from T.N.nodes('SecondaryServices') as S(N)
        for xml path(''), type
      ).value('substring(text()[1], 2)', 'varchar(max)') as SecondaryServices,
      T.N.value('(Description/text())[1]', 'varchar(max)') as Description
    from @XML.nodes('/root/DocInfo') as T(N)
    

    如果您想在一列中包含所有服务,您可以在子查询的节点部分中使用不同的 xPath。

    select
      T.N.value('(CompanyName/text())[1]', 'varchar(250)') as CompanyName,
      T.N.value('(WebsiteUrl/text())[1]', 'varchar(250)') as WebsiteUrl,
      (
        select ', '+P.N.value('text()[1]', 'varchar(max)')
        from T.N.nodes('PrimaryServices,SecondaryServices') as P(N)
        for xml path(''), type
      ).value('substring(text()[1], 2)', 'varchar(max)') as Services,
      T.N.value('(Description/text())[1]', 'varchar(max)') as Description
    from @XML.nodes('/root/DocInfo') as T(N)
    

    【讨论】:

    • 谢谢。这将获取 xml 和值。我如何获得价值? T
    • @user971823 你想要怎样的价值观?在一列中,单独的列,单独的行或其他东西或......?
    • 一列逗号分隔是理想的。
    • 太棒了。这正是我所需要的。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多