如何在 oracle XMLTYPE XMLTABLE 中支持 1 级路径目录

Posted

技术标签:

【中文标题】如何在 oracle XMLTYPE XMLTABLE 中支持 1 级路径目录【英文标题】:how to back 1 level of path directory in oracle XMLTYPE XMLTABLE 【发布时间】:2021-06-21 16:36:24 【问题描述】:

我试图在路径中支持 1 级文件夹,但它不是工作属性。 我尝试使用“../”和“./”但没有用。 我如何在 Oracle 中做到这一点?

WITH xmlPrePos as 
(
  select
    IDPraga,
    IDUsina,
    replace(valor, '<?xml version="1.0" encoding="utf-16"?>','') as XML    
  from dbo_Config
  where SiglaCategoria = 'ConfigFiltros' and Sigla='ConfigFiltros'
)
    SELECT 
        IDPraga,
        IDUsina,
        IDTpVinculo,
        Descricao,
        Reforma
    FROM xmlPrePos,
        xmltable('/ConfiguracaoFiltros/TpVinculoConfigFiltros/TpVinculoConfigFiltros'
    passing XMLTYPE(xmlPrePos.XML)
    COLUMNS 
        IDTpVinculo INT path 'IDTpVinculo',
        Descricao VARCHAR(100) path 'Descricao',
        Reforma VARCHAR(100) path '../../SituacaoAreasConfigFiltros/Reforma');

最后一行是我遇到问题的代码。 我的回报是空的。

XML>

<ConfiguracaoFiltros xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <SituacaoAreasConfigFiltros>
    <Reforma>VERDADEIRO</Reforma>
    <Bloqueio>NAO_IMPORTA</Bloqueio>
  </SituacaoAreasConfigFiltros>
  <TpVinculoConfigFiltros>
    <TpVinculoConfigFiltros>
      <IDTpVinculo>11</IDTpVinculo>
      <Descricao>ARRENDAMENTO / PARCERIA</Descricao>
    </TpVinculoConfigFiltros>
    <TpVinculoConfigFiltros>
      <IDTpVinculo>12</IDTpVinculo>
      <Descricao>PROPRIA</Descricao>
    </TpVinculoConfigFiltros>
  </TpVinculoConfigFiltros>
</ConfiguracaoFiltros>

版本>

Oracle 数据库 11g 企业版版本 11.1.0.6.0 - 64 位生产 PL/SQL 版本 11.1.0.6.0 - 生产 “核心 11.1.0.6.0 生产” 适用于 Linux 的 TNS:版本 11.1.0.6.0 - 生产 NLSRTL 版本 11.1.0.6.0 - 生产

等待结果>

【问题讨论】:

请提供您的 oracle 版本和您的 xml 数据示例 ...以及您当前和预期的结果。为什么要去掉 ?xml 标头? 在问题中添加信息 11.1 是一个非常老旧且漏洞百出的版本... 我知道..但不幸的是公司仍在使用的版本 【参考方案1】:

由于在 11g 中返回树似乎不起作用,您可以改为使用两个 XMLTable 调用:

WITH xmlPrePos as 
(
  select
    IDPraga,
    IDUsina,
    replace(valor, '<?xml version="1.0" encoding="utf-16"?>','') as XML    
  from dbo_Config
  where SiglaCategoria = 'ConfigFiltros' and Sigla='ConfigFiltros'
)
    SELECT 
        IDPraga,
        IDUsina,
        x2.IDTpVinculo,
        x2.Descricao,
        x1.Reforma
    FROM xmlPrePos
    CROSS JOIN xmltable(
        '/ConfiguracaoFiltros'
        passing XMLTYPE(xmlPrePos.XML)
        COLUMNS 
            Reforma VARCHAR(100) path 'SituacaoAreasConfigFiltros/Reforma',
            TpVinculoConfigFiltros xmltype path 'TpVinculoConfigFiltros'
    ) x1
    CROSS JOIN xmltable(
        '/TpVinculoConfigFiltros/TpVinculoConfigFiltros'
        passing x1.TpVinculoConfigFiltros
        COLUMNS 
            IDTpVinculo INT path 'IDTpVinculo',
            Descricao VARCHAR(100) path 'Descricao'
    ) x2;

你的例子得到:

IDPRAGA IDUSINA IDTPVINCULO DESCRICAO               REFORMA   
------- ------- ----------- ----------------------- ----------
      3       1          11 ARRENDAMENTO / PARCERIA VERDADEIRO
      3       1          12 PROPRIA                 VERDADEIRO

db<>fiddle

正如@Sayan 所说,我也曾评论过,您不需要删除 XML 标头;它可以与它一起使用,并且不需要 CTE:

    SELECT 
        dc.IDPraga,
        dc.IDUsina,
        x2.IDTpVinculo,
        x2.Descricao,
        x1.Reforma
    FROM dbo_Config dc
    CROSS JOIN xmltable(
        '/ConfiguracaoFiltros'
        passing XMLTYPE(dc.valor)
        COLUMNS 
            Reforma VARCHAR(100) path 'SituacaoAreasConfigFiltros/Reforma',
            TpVinculoConfigFiltros xmltype path 'TpVinculoConfigFiltros'
    ) x1
    CROSS JOIN xmltable(
        '/TpVinculoConfigFiltros/TpVinculoConfigFiltros'
        passing x1.TpVinculoConfigFiltros
        COLUMNS 
            IDTpVinculo INT path 'IDTpVinculo',
            Descricao VARCHAR(100) path 'Descricao'
    ) x2;

db<>fiddle

【讨论】:

它就像一个魅力 \o/.. 非常感谢【参考方案2】:

如果您的数据如下所示:

<?xml version="1.0" encoding="utf-16"?>
  <ConfiguracaoFiltros>
    <TpVinculoConfigFiltros>
      <TpVinculoConfigFiltros>
        <IDTpVinculo>1</IDTpVinculo>
        <Descricao>Test1</Descricao>
      </TpVinculoConfigFiltros>
    </TpVinculoConfigFiltros>
    <SituacaoAreasConfigFiltros>
      <Reforma>Reforma Test1</Reforma>
    </SituacaoAreasConfigFiltros>
  </ConfiguracaoFiltros>

您可以在../../ 之前简单地添加./: DBFiddle

WITH 
dbo_Config as (
select
  'ConfigFiltros' SiglaCategoria,
  'ConfigFiltros' Sigla,
  'IDPraga' IDPraga,
  'IDUsina' IDUsina,
  q'[<?xml version="1.0" encoding="utf-16"?>
  <ConfiguracaoFiltros>
    <TpVinculoConfigFiltros>
      <TpVinculoConfigFiltros>
        <IDTpVinculo>1</IDTpVinculo>
        <Descricao>Test1</Descricao>
      </TpVinculoConfigFiltros>
    </TpVinculoConfigFiltros>
    <SituacaoAreasConfigFiltros>
      <Reforma>Reforma Test1</Reforma>
    </SituacaoAreasConfigFiltros>
  </ConfiguracaoFiltros>
  ]' as valor
from dual
)
,xmlPrePos as 
(
  select
    IDPraga,
    IDUsina,
    replace(valor, '<?xml version="1.0" encoding="utf-16"?>','') as XML    
  from dbo_Config
  where SiglaCategoria = 'ConfigFiltros' and Sigla='ConfigFiltros'
)
    SELECT 
        IDPraga,
        IDUsina,
        IDTpVinculo,
        Descricao,
        Reforma
    FROM xmlPrePos,
        xmltable('/ConfiguracaoFiltros/TpVinculoConfigFiltros/TpVinculoConfigFiltros'
    passing XMLTYPE(xmlPrePos.XML)
    COLUMNS 
        IDTpVinculo INT path 'IDTpVinculo',
        Descricao VARCHAR(100) path 'Descricao',
        Reforma VARCHAR(100) path './../../SituacaoAreasConfigFiltros/Reforma');

但我不会删除 &lt;?xml ...?&gt; 标头: DBFiddle2

WITH 
dbo_Config as (
select
  'ConfigFiltros' SiglaCategoria,
  'ConfigFiltros' Sigla,
  'IDPraga' IDPraga,
  'IDUsina' IDUsina,
  q'[<?xml version="1.0" encoding="utf-16"?>
  <ConfiguracaoFiltros>
    <TpVinculoConfigFiltros>
      <TpVinculoConfigFiltros>
        <IDTpVinculo>1</IDTpVinculo>
        <Descricao>Test1</Descricao>
      </TpVinculoConfigFiltros>
    </TpVinculoConfigFiltros>
    <SituacaoAreasConfigFiltros>
      <Reforma>Reforma Test1</Reforma>
    </SituacaoAreasConfigFiltros>
  </ConfiguracaoFiltros>
  ]' as valor
from dual
)
,xmlPrePos as 
(
  select
    IDPraga,
    IDUsina,
    valor as XML    
  from dbo_Config
  where SiglaCategoria = 'ConfigFiltros' and Sigla='ConfigFiltros'
)
    SELECT 
        IDPraga,
        IDUsina,
        IDTpVinculo,
        Descricao,
        Reforma
    FROM xmlPrePos,
        xmltable('/ConfiguracaoFiltros/TpVinculoConfigFiltros/TpVinculoConfigFiltros'
    passing XMLTYPE(xmlPrePos.XML)
    COLUMNS 
        IDTpVinculo INT path 'IDTpVinculo',
        Descricao VARCHAR(100) path 'Descricao',
        Reforma VARCHAR(100) path './../../SituacaoAreasConfigFiltros/Reforma');

相同的示例,但您在 DBFiffle 上更新了数据: https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=23c0d9d500d0b87f1bc3469efd4960b9

【讨论】:

我试过了,但返回 NULL 应该带“VERDADEIRO”.. 或“Reforma Test1”(在你的 xml 示例中) “改革”列不断返回 NULL @FernandoFefu 是的,我只记得 11.1 中有一个错误。等一下,我将添加另一个答案并提供解决方法【参考方案3】:

Oracle

WITH 
dbo_Config as (
select
  'ConfigFiltros' SiglaCategoria,
  'ConfigFiltros' Sigla,
  'IDPraga' IDPraga,
  'IDUsina' IDUsina,
  q'[<ConfiguracaoFiltros xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <SituacaoAreasConfigFiltros>
    <Reforma>VERDADEIRO</Reforma>
    <Bloqueio>NAO_IMPORTA</Bloqueio>
  </SituacaoAreasConfigFiltros>
  <TpVinculoConfigFiltros>
    <TpVinculoConfigFiltros>
      <IDTpVinculo>11</IDTpVinculo>
      <Descricao>ARRENDAMENTO / PARCERIA</Descricao>
    </TpVinculoConfigFiltros>
    <TpVinculoConfigFiltros>
      <IDTpVinculo>12</IDTpVinculo>
      <Descricao>PROPRIA</Descricao>
    </TpVinculoConfigFiltros>
  </TpVinculoConfigFiltros>
</ConfiguracaoFiltros>
  ]' as valor
from dual
)
,xmlPrePos as 
(
  select
    IDPraga,
    IDUsina,
    valor as XML    
  from dbo_Config
  where SiglaCategoria = 'ConfigFiltros' and Sigla='ConfigFiltros'
)
    SELECT 
        IDPraga,
        IDUsina,
        xdata.*
    FROM xmlPrePos,
        xmltable(
          '
          for $x in ./ConfiguracaoFiltros
            for $y in $x/TpVinculoConfigFiltros/TpVinculoConfigFiltros
              return <row>
                       $y
                       $x/SituacaoAreasConfigFiltros/Reforma
                     </row>'
    passing XMLTYPE(xmlPrePos.XML)
    COLUMNS 
        xdata        xmltype      path '.',
        IDTpVinculo  INT          path './TpVinculoConfigFiltros/IDTpVinculo',
        Descricao    VARCHAR(100) path './TpVinculoConfigFiltros/Descricao',
        Reforma      VARCHAR(100) path 'Reforma'
        ) xdata;

【讨论】:

以上是关于如何在 oracle XMLTYPE XMLTABLE 中支持 1 级路径目录的主要内容,如果未能解决你的问题,请参考以下文章

如何在 oracle XMLTYPE XMLTABLE 中支持 1 级路径目录

如何从存储过程中读取 c# oracle XmlType

如何使用 java.sql 包中的 rs.getSQLXML() 函数从 Oracle 数据库中获取 XMLType 列?

Oracle XMLTABLE - 如何从 XMLType 中删除节点?

初识Oracle的XMLType

在 Oracle 查询中连接 XMLType 节点