【问题标题】:SQL: How to find rows by filtering on a value within an XML columnSQL:如何通过过滤 XML 列中的值来查找行
【发布时间】:2018-07-07 21:55:51
【问题描述】:

我有一个 XML 数据类型的字段,下面是我保存在该字段中的 XML 数据示例。现在,我想通过使用下面的查询选择在<SiteId> 标签内具有“1”的数据,但没有结果。

SELECT [SettingsID]
      ,[XMLData]
FROM Settings
Where [XMLData].exist('/Settings/SiteId/text()[contains(.,"1")]') =1 


XMLDATA sample

<Settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <SiteId>1</SiteId>
  <ModuleId xsi:nil="true" />
  <TabId xsi:nil="true" />
  <Version>0</Version>
</Settings>

有人对此有想法吗?

【问题讨论】:

  • 您使用的是哪个 dbms? (该查询是特定于产品的。)
  • @jarlh, ms sql 2012
  • @crisgomez 我刚刚针对我的模型表测试了您的查询(请参阅答案),它似乎有效...请注意,contains 会在任何文本中找到包括 1 在内的任何文本位置
  • @crisgomez 我刚刚改写了你的标题 - 如果我没有正确理解,请检查并回滚更改!

标签: xml tsql xpath sql-server-2012 xquery


【解决方案1】:

您的问题的标题 - 大概 - 具有误导性......

我认为您不是在寻找全文搜索,而是寻找适当的XQuery 来查找具有给定条件的条目。

试试这个:

DECLARE @mockupTable TABLE(SettingsID INT IDENTITY, XMLData XML);
INSERT INTO @mockupTable VALUES
 (N'<Settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <SiteId>1</SiteId>
  <ModuleId xsi:nil="true" />
  <TabId xsi:nil="true" />
  <Version>0</Version>
</Settings>')
,(N'<Settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <SiteId>2</SiteId>
  <ModuleId xsi:nil="true" />
  <TabId xsi:nil="true" />
  <Version>0</Version>
</Settings>');

--查询测试,如果有&lt;SiteId&gt;,其text()1

SELECT[SettingsID]
      ,[XMLData]
FROM @mockupTable
Where [XMLData].exist('/Settings/SiteId[text()="1"]') =1;

您可以将1 引入查询,只需使用sql:variable("@SomeIntVariable") 而不是"1"

DECLARE @id INT=2;
SELECT[SettingsID]
      ,[XMLData]
FROM @mockupTable
Where [XMLData].exist('/Settings/SiteId[text()=sql:variable("@id")]') =1 

更新

要尽可能多地创建它,您可以使用 深度搜索//*: 来省略任何命名空间:

SELECT[SettingsID]
      ,[XMLData]
FROM @mockupTable
Where [XMLData].exist('//*:SiteId[text()="1"]') =1;

【讨论】:

  • 谢谢@Shnugo,这是可行的,但是当我使用实际的表时,这不起作用。不知道为什么。
  • @crisgomez “不工作”是什么意思?错误?没有结果?有没有你没有提到的命名空间?结构可能不同(您没有发布 full 示例吗)?
  • @crisgomez 尝试将您的XPath 设置为Where [XMLData].exist('//*:SiteId[text()="1"]') =1; 这将执行深度搜索(省略父节点)并忽略命名空间...
  • 有效!信哥,非常感谢!顺便说一句,我所说的“不工作”是没有结果。
  • @crisgomez 太棒了!在这种情况下,我假设给定的示例 XML 以某种方式减少/简化,因此 XPath 没有命中。
【解决方案2】:

也许很傻,但我很理解你的问题,这可能工作正常:

SELECT [SettingsID],[XMLData]
FROM Settings
Where [XMLData] LIKE '%<SiteId>1</SiteId>%' 

【讨论】:

  • 嗨 P.ejH,我们有相同的实现,由于性能问题,我将其更改为全文搜索。
  • 根据示例代码,给定的列是原生 XML。 LIKE 需要先转换为NVARCHAR(MAX)(这在这里相当昂贵......)
  • @crisgomez 使用.exist() 的正确XML 查询是肯定的! - 比全文搜索快...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-06
  • 1970-01-01
  • 2018-07-08
  • 1970-01-01
  • 2023-04-07
相关资源
最近更新 更多