【问题标题】:Can't figure out how to search XML column in my table不知道如何在我的表中搜索 XML 列
【发布时间】:2018-01-09 10:12:25
【问题描述】:

我有一个名为 v_EpisodeAudit 的表,其中有一个名为 EventData 的列,其中包含 XML 数据。 XML 数据因行而异,因此一条记录的该列中的 XML 数据可能如下所示:

<AddMDMDocument>
  <EpisodeMDMId>282521</EpisodeMDMId>
  <OncologyReferral>0</OncologyReferral>
  <SpecialPalliativeReferral>0</SpecialPalliativeReferral>
  <SurgeonReferral>0</SurgeonReferral>
  <MDMReport>0</MDMReport>
  <GPReferral>0</GPReferral>
  <GPReferralApproval>0</GPReferralApproval>
  <GeneralPalliativeCare>0</GeneralPalliativeCare>
  <AuditLogin>mkell010</AuditLogin>
  <AuditTrust>4</AuditTrust>
  <Error />
</AddMDMDocument>

而另一行可能包含以下 XML 数据:

<CloseEpisode>
  <EpisodeId>652503</EpisodeId>
  <TrackingStatusId>9</TrackingStatusId>
  <TrackingClosureReason>100</TrackingClosureReason>
  <DateOfTrackingClosure>Sep 25 2017 12:37PM</DateOfTrackingClosure>
  <AuditLogin>ccass001</AuditLogin>
  <AuditTrust>1</AuditTrust>
  <Error />
</CloseEpisode>

还有更多不同类型/配置的 XML 数据。今天早上我已经阅读了大约 20 个不同的来源,试图找出如何搜索本专栏中的 XML 数据以获取 CloseEpisode XML 中的特定 EpisodeId,但我终生无法弄清楚。任何人都可以帮助我查询在此列中找到指定的 EpisodeId 吗?

【问题讨论】:

    标签: sql-server xml tsql xpath xquery


    【解决方案1】:

    可以非常通用地查询 XML。一些方法:

    DECLARE @v_EpisodeAudit TABLE(ID INT IDENTITY, [EventData] XML);
    INSERT INTO @v_EpisodeAudit VALUES
     (N'<AddMDMDocument>
      <EpisodeMDMId>282521</EpisodeMDMId>
      <OncologyReferral>0</OncologyReferral>
      <SpecialPalliativeReferral>0</SpecialPalliativeReferral>
      <SurgeonReferral>0</SurgeonReferral>
      <MDMReport>0</MDMReport>
      <GPReferral>0</GPReferral>
      <GPReferralApproval>0</GPReferralApproval>
      <GeneralPalliativeCare>0</GeneralPalliativeCare>
      <AuditLogin>mkell010</AuditLogin>
      <AuditTrust>4</AuditTrust>
      <Error />
    </AddMDMDocument>')
    ,(N'<CloseEpisode>
      <EpisodeId>652503</EpisodeId>
      <TrackingStatusId>9</TrackingStatusId>
      <TrackingClosureReason>100</TrackingClosureReason>
      <DateOfTrackingClosure>Sep 25 2017 12:37PM</DateOfTrackingClosure>
      <AuditLogin>ccass001</AuditLogin>
      <AuditTrust>1</AuditTrust>
      <Error />
    </CloseEpisode>');00
    

    --这将返回第二层的第一个节点

    SELECT ID
          ,vEA.[EventData].value(N'local-name(/*[1]/*[1])',N'nvarchar(max)') AS NodeName
          ,vEA.[EventData].value(N'/*[1]/*[1]/text()[1]',N'nvarchar(max)') AS NodeValue
    FROM @v_EpisodeAudit AS vEA
    

    --这将返回第二层的所有节点,并使用WHERELIKE 查找Episode..Id 元素

    SELECT ID
          ,SecondLevelNode.Nd.value(N'local-name(.)',N'nvarchar(max)') AS NodeName
          ,SecondLevelNode.Nd.value(N'text()[1]',N'nvarchar(max)') AS NodeValue
    FROM @v_EpisodeAudit AS vEA
    OUTER APPLY vEA.[EventData].nodes(N'/*/*') AS SecondLevelNode(Nd)
    WHERE SecondLevelNode.Nd.value(N'local-name(.)',N'nvarchar(max)') LIKE 'Episode%' --or LIKE 'Episode%Id'
    

    --类似但在 XQuery 级别进行过滤

    SELECT ID
          ,SecondLevelNode.Nd.value(N'local-name(.)',N'nvarchar(max)') AS NodeName
          ,SecondLevelNode.Nd.value(N'text()[1]',N'nvarchar(max)') AS NodeValue
    FROM @v_EpisodeAudit AS vEA
    OUTER APPLY vEA.[EventData].nodes(N'/*/*[substring(local-name(),1,7)="Episode"]') AS SecondLevelNode(Nd)
    

    【讨论】:

      【解决方案2】:

      使用xml查询功能

      select EventData.value('(/CloseEpisode/EpisodeId)[1]','int')
      from v_EpisodeAudit
      where EventData.value('local-name(/*[1])','varchar(100)')='CloseEpisode'
      

      或许

      select EventData 
      from @v_EpisodeAudit
      where EventData.value('(/CloseEpisode/EpisodeId)[1]','int')=652503
      

      取决于你想要做什么。

      如果你不知道根节点名称,你可以使用

       select EventData.value('(//EpisodeId)[1]','int')
       from v_EpisodeAudit
       where EventData.exist('//EpisodeId')=1
      

      https://docs.microsoft.com/en-us/sql/t-sql/xml/value-method-xml-data-type

      【讨论】:

      • 太棒了,就像一个魅力。谢谢。后续问题。如果我想在不知道 XML 父级的情况下找到 EpisodeId 怎么办,例如。不知道它在 CloseEpisode 中 - 无论它在哪里,我如何找到 EpisodeId?
      • @ailinmcc666 难道我的回答没有完全涵盖这个问题(未知元素名称)吗?
      • 我很抱歉,确实如此。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多