【问题标题】:Oracle query to extract XML Element values from a table dynamically从表中动态提取 XML 元素值的 Oracle 查询
【发布时间】:2019-12-25 21:29:10
【问题描述】:

我正在寻找可以在具有存储 XML 的列之一的表上运行的 Oracle 查询 此查询应动态地采用查询中的 xpath 以从所有节点中提取字符串。我在下面尝试过,但我必须对 xpath 进行硬编码。我不想硬编码 xpath。

有没有办法生成 xpath,基于 XML 的结构(结构可能会有所不同)动态提取 xml 节点值?

我需要的输出是xml节点的提取值。

我试过了:

SELECT xmltype(XMLCOLUMN).EXTRACT('/report/fulcriteria/text()'),
       xmltype(XMLCOLUMN).EXTRACT('/report/conumb/text()'),
       xmltype(XMLCOLUMN).EXTRACT('/report/dup/text()'),
       xmltype(XMLCOLUMN).EXTRACT('/report/reportdup[1]/dupsource/text()'),
       xmltype(XMLCOLUMN).EXTRACT('/report/reportdup[2]/dupsource/text()'),
       xmltype(XMLCOLUMN).EXTRACT('/report/reportdup[2]/dupnumb/text()'),
       xmltype(XMLCOLUMN).EXTRACT('/report/reportdup[3]/dupsource/text()'),
       xmltype(XMLCOLUMN).EXTRACT('/report/reportdup[3]/dupnumb/text()') . 
       xmltype(XMLCOLUMN).EXTRACT('/report/final/dup/text()'),
  FROM MYTABLE

【问题讨论】:

  • "这个查询应该动态地使用查询中的 xpath 从所有节点中提取字符串" 你是如何提供这个动态路径的?它在另一张桌子上吗?它是在绑定变量中传递的吗?还有什么?请edit 使用minimal reproducible example 提出您的问题,其中包含有关您如何生成查询的所有详细信息。
  • @MT0:让我澄清一下,我有一个存储 XML 文件的表 MYTABLE.XMLCOLUMN。我没有将 xpath 存储在任何表中。 XML 遵循某种结构,其中包含重复的块。因为我知道结构,所以我对 xpath 进行了硬编码。我需要一个表来存储 XPATH 吗?
  • 你说“查询应该动态地采用xpath”;如果它是动态的,那么您需要从某个地方传递路径(告诉我们在哪里以及如何)。如果它不是动态的,那么您可以使用静态路径(我不确定这个问题的意义是什么)。无论您选择什么,您都需要告诉我们您的规格是什么,因为我们可以猜测并编造一些东西,但它可能不会完全符合您的意图。那么你为什么不准确地计算出你想要的东西,edit 你的问题,minimal reproducible example 告诉我们那是什么。
  • 如果您只想列出 XML 文档中的所有路径和相应的值,那么这是 stackoverflow.com/q/49039401/1509264 的副本
  • @MT0 :从那个帖子中,我在“PASSING d.xml AS”doc”行收到错误,说“d.xml 是无效标识符”不知道为什么 xml 是 XMLTYPE 的列。

标签: sql oracle xpath xmltype


【解决方案1】:

将包含动态路径的表与包含 XML 的表连接起来,然后使用 XMLTABLE 提取值:

Oracle 设置

CREATE TABLE mytable ( id, xmlcolumn ) AS
SELECT 1, '<report>
  <fulcriteria>1</fulcriteria>
  <conumb>2</conumb>
  <dup>3</dup>
  <reportdup><dupsource>4.1</dupsource></reportdup>
  <reportdup><dupsource>4.2a</dupsource><dupnumb>4.2b</dupnumb></reportdup>
  <reportdup><dupsource>4.3a</dupsource><dupnumb>4.3b</dupnumb></reportdup>
  <final><dup>5</dup></final>
</report>' FROM DUAL;

CREATE TABLE paths ( path ) AS
SELECT '/report/fulcriteria' FROM DUAL UNION ALL
SELECT '/report/conumb' FROM DUAL UNION ALL
SELECT '/report/dup' FROM DUAL UNION ALL
SELECT '/report/reportdup[1]/dupsource' FROM DUAL UNION ALL
SELECT '/report/reportdup[2]/dupsource' FROM DUAL UNION ALL
SELECT '/report/reportdup[2]/dupnumb' FROM DUAL UNION ALL
SELECT '/report/reportdup[3]/dupsource' FROM DUAL UNION ALL
SELECT '/report/reportdup[3]/dupnumb'  FROM DUAL UNION ALL
SELECT '/report/final/dup' FROM DUAL;

查询 1

SELECT t.id,
       p.path,
       x.value
FROM   MYTABLE t
       CROSS JOIN PATHS p
       CROSS JOIN XMLTABLE(
         p.path
         PASSING XMLTYPE( t.xmlcolumn )
         COLUMNS
           value VARCHAR2(4000) PATH '.'
       ) x

查询 2

SELECT t.id,
       p.path,
       XMLQUERY(
         (p.path || '/text()')
         PASSING XMLTYPE( t.xmlcolumn )
         RETURNING CONTENT
       ) AS value
FROM   MYTABLE t
       CROSS JOIN PATHS p;

查询 3

SELECT t.id,
       p.path,
       XMLTYPE( t.xmlcolumn ).EXTRACT(p.path||'/text()').getStringVal() AS value
FROM   MYTABLE t
       CROSS JOIN PATHS p;

输出

身份证 |路径 |价值 -: | :----------------------------- | :---- 1 | /报告/标准 | 1 1 | /报告/conumb | 2 1 | /报告/重复 | 3 1 | /report/reportdup[1]/dupsource | 4.1 1 | /report/reportdup[2]/dupsource | 4.2a 1 | /report/reportdup[2]/dupnumb | 4.2b 1 | /report/reportdup[3]/dupsource | 4.3a 1 | /report/reportdup[3]/dupnumb | 4.3b 1 | /报告/最终/重复 | 5

db小提琴here

【讨论】:

  • 唉,我无法使用默认命名空间。 db小提琴here
  • @T-Gergely 我无法立即找出XMLTABLE 的命名空间问题,但在此db<>fiddle 中有使用XMLQUERY 和(已弃用的)EXTRACT 函数的工作版本。
  • 感谢您的提示。我有一个更复杂的查询,并且只有 XMLTYPE.EXTRACT 成员函数(可能不会被弃用)有效,并且只能使用 NO_XML_QUERY_REWRITE 提示。 XMLQUERY 和已弃用的 EXTRACT、EXTRACTVALUE 都失败了,甚至不一致:没有行、空值、ORA-600 [qmxqrsWriteItemToOpn:itemTyp] 和其他错误。 (12.1 企业版,补丁不太旧。)
猜你喜欢
  • 1970-01-01
  • 2011-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多