【问题标题】:SQL Server 2008 XML query issueSQL Server 2008 XML 查询问题
【发布时间】:2010-07-14 08:43:04
【问题描述】:

我正在使用 SQL Server 2008 Enterprise + VSTS 2008 + C# + .Net 3.5 + ASP.Net + IIS 7.0 来开发一个简单的 Web 应用程序。在我的数据库表中,我有一个 XML 类型的列。内容如下,

如果 Title 包含“软件工程师”或 Info 包含“软件开发”,我想获取表中所有行的 AdditionalInfoList。我的问题是如何高效地编写这样的查询?

<People>
  <Item Name="Username" Value="George" />
  <Item Name="Info" Value="Software Development Information" />
  <Item Name="Title" Value="Software Engineer in Backend" />
  <AdditionalInfoList>
    <AdditionalInfoListItem Guid="xxx" type="type1" />
    <AdditionalInfoListItem Guid="yyy" type="type2" />
  </AdditionalInfoList>
</People>

【问题讨论】:

  • 我目前的解决方案是将所有XML读入一个XML字符串,然后解析XML字符串,我认为效率较低。我想找到一个更有效的解决方案。

标签: c# xml sql-server-2008 tsql visual-studio-2008


【解决方案1】:

你需要做这样的事情:

SELECT
    t.ID, -- or whatever you need from the table where the XML is located
    tbl.People.query('AdditionalInfoList')
FROM
    dbo.YourTable  t
CROSS APPLY
    t.(xmlcolumn).nodes('/People') AS Tbl(People)
WHERE
    tbl.People.value('(Item[@Name="Info"]/@Value)[1]', 'varchar(50)') LIKE '%Software Development%'
    OR
    tbl.People.value('(Item[@Name="Title"]/@Value)[1]', 'varchar(50)') LIKE '%Software Engineer%'

这应该会给你所有你感兴趣的条目。

解释

CROSS APPLY 创建了一个“虚拟”表,您需要为其命名 - 这里:Tbl(People)。这个名字是什么并不重要,也不区分大小写,所以Tbltbl 是相同的。

如果您想将 Guid 和类型作为与&lt;AdditionalInfoList&gt; 分开的值,您需要在此处使用此查询:

SELECT
    t.ID,
    --tbl.People.value('(Item[@Name="Info"]/@Value)[1]', 'varchar(50)') AS 'Info',
    --tbl.People.value('(Item[@Name="Title"]/@Value)[1]', 'varchar(50)') AS 'Title'
    Adtl.Info.value('(@Guid)[1]', 'varchar(50)') AS 'GUID',
    Adtl.Info.value('(@type)[1]', 'varchar(50)') AS 'Type'
FROM
    @table t
CROSS APPLY 
    t.xmlcolumn.nodes('/People') AS Tbl(People)
CROSS APPLY 
    Tbl.People.nodes('AdditionalInfoList/AdditionalInfoListItem') AS Adtl(Info)
WHERE
    Tbl.People.value('(Item[@Name="Info"]/@Value)[1]', 'varchar(50)') LIKE '%Software Development%'
    OR
    Tbl.People.value('(Item[@Name="Title"]/@Value)[1]', 'varchar(50)') LIKE '%Software Engineer%'

您基本上必须进行第二次 CROSS APPLY(这会损害您的表现!)才能从 Tbl.Person 获取每个条目的“附加信息”列表,并从中提取 Guid 和类型值。

查看SQL Server 2005 XQuery and XML DML 介绍 - 大约在文章中间,有一节介绍如何使用.nodes() 功能。很有帮助!

【讨论】:

  • TBL 是什么?以及如何从检索到的每个匹配行的信息中获取 GUID 和类型?
  • 对于 TBL 我很困惑,因为您同时使用 TBL 和“tbl”。
  • @George2:我相信这会更快,是的,而且更实用。为什么?因为 XQuery 的东西在 SQL Server 中得到了很好的优化,我认为能够从结构中检索实际值而不是解析字符串更加健壮。
  • @George2: CROSS APPLY 适用于一组数据 - 例如来自您的函数的一组行,或者来自 XQuery .nodes() 函数的一组“伪行” - 而 .nodes() 确实也是一个函数!它为 XML 中与 .nodes() 函数中的 XPath 表达式匹配的每个条目返回“一行”。
  • @George2:是的,您可以将其作为字符串读回,然后将其加载到 XmlDocument 或 XDocument (Linq-to-XML) 中 - 任何适合您的方式
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-01
  • 2011-04-10
相关资源
最近更新 更多