如何在SQL中查询XML并返回所有节点的列表

问题描述 投票:0回答:1

我有一个包含一个 XML 列的 SQL 表,我想查询 XML 并获取

id/@extension
以及所有
observation/code
的列表。但是它总是返回空结果。我已经隔离了一个包含代表性测试数据的示例表,请参见下文

CREATE TABLE study123 (
    ID integer,
    Title varchar(25),
    STXML XML
);

INSERT INTO study123 (
    ID,
    Title,
    STXML
) VALUES
(1, 'ST_Cardio', '<MeasurementDocument xmlns="urn:hl7-org:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <id extension="68c65a01-2188-486c-adde-a854453ff817" />
  <code code="ST_Cardio" displayName="CardioLife60+" />
  <title>CardioLife 60+</title>
  <text>Prospective validation of CardioLife algorithms age 60+</text>
  <component>
    <section>
      <entry typeCode="DRIV">
        <observation classCode="OBS" moodCode="CRT">
          <code code="TMPL_1120000364" displayName="CV TEE/CARDIO DAILYLOG" />
        </observation>
      </entry>
      <entry typeCode="DRIV">
        <observation classCode="OBS" moodCode="CRT">
          <code code="TMPL_1120000365" displayName="CV TEE/CARDIO VITAL SIGNS CHECKLIST" />
        </observation>
      </entry>
    </section>
  </component>
</MeasurementDocument>'),
(2, 'ST_Cardio', '<MeasurementDocument xmlns="urn:hl7-org:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <id extension="a3be767f-1315-4e2b-ab4e-11a238d7f9a1" />
  <code code="ST_Diabetics" displayName="DiabeticsObs" />
  <title>Diabetics Observation 2023-2024</title>
  <text>Diabetics Observation 2023-2024 Extended II</text>
  <component>
    <section>
      <entry typeCode="DRIV">
        <observation classCode="OBS" moodCode="CRT">
          <code code="TMPL_1173900045" displayName="CVR PHYSIC DIABETICS" />
        </observation>
      </entry>
      <entry typeCode="DRIV">
        <observation classCode="OBS" moodCode="CRT">
          <code code="TMPL_1177400741" displayName="CVR DIABETICS OBSERVATIONWEEK" />
        </observation>
      </entry>
      <entry typeCode="DRIV">
        <observation classCode="OBS" moodCode="CRT">
          <code code="TMPL_1189600034" displayName="CVR DIABETICS REVALIDATION CHECKLIST" />
        </observation>
      </entry>
    </section>
  </component>
</MeasurementDocument>
');

这是我尝试过的,但这只会给出所有空的 NULL 结果。当我尝试仅查询每个研究中的单个 ID 和文本描述时,列为 NULL

-- test columns are all NULL(?)
SELECT 
    ID,
    Title,
    STXML,
    STXML.value('(/MeasurementDocument/id/@extension)[1]', 'nvarchar(100)') AS test_id,
    STXML.value('(/MeasurementDocument/title)[1]', 'nvarchar(100)') AS test_title,
    STXML.value('(/MeasurementDocument/text)[1]', 'nvarchar(100)') AS test_text
FROM 
    study123

当我尝试查询每个研究的所有模板时,结果为空,即使第一个有 2 个模板,第二个有 3 个模板。

-- no records, empty result
select * from 
(select 
    ID,
    Title,
    TheTemplate.value('(./observation/code/@code)[1]', 'varchar(1000)') as tmpl_code
from 
    study123 CROSS APPLY
    STXML.nodes('MeasurementDocument/component/section/entry[@typeCode="DRIV"]/observation') AS AllTemplates(TheTemplate)
)  as Result

我尝试搜索示例并询问 ChatGPT,但我感觉查询 XML 的 SQL Server 示例并不能很好地代表现实世界的 xml 示例,或者它们缺少某些内容(?)。

sql sql-server xml
1个回答
0
投票

您需要使用

WITH XMLNAMESPACES
添加默认命名空间,并且您已将
observation
节点加倍。

您还可以避免用另一个

CROSS APLY nodes
引用根节点。

WITH XMLNAMESPACES (DEFAULT 'urn:hl7-org:v3')
SELECT 
    ID,
    Title,
    doc.value('(id/@extension)[1]', 'nvarchar(100)') AS test_id,
    doc.value('(title/text())[1]', 'nvarchar(100)') AS test_title,
    doc.value('(text/text())[1]', 'nvarchar(100)') AS test_text,
    TheTemplate.value('(code/@code)[1]', 'nvarchar(1000)') as tmpl_code
from 
    study123 s
CROSS APPLY
    s.STXML.nodes('MeasurementDocument') x1(doc)
CROSS APPLY
    x1.doc.nodes('component/section/entry[@typeCode="DRIV"]/observation') AS AllTemplates(TheTemplate);

db<>小提琴

© www.soinside.com 2019 - 2024. All rights reserved.