无法弄清楚如何在我的表中搜索XML列

时间:2018-01-09 10:12:25

标签: sql-server xml tsql xpath xquery

我有一个名为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的查询吗?

2 个答案:

答案 0 :(得分:4)

可以非常一般地查询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

- 这将返回sevond级别的所有节点,并使用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)

答案 1 :(得分:3)

使用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