Oracle SQL 中的 REGEXP_COUNT 缓冲区太小

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

我有以下 SQL:

            with q1 ( Tdata,Key) AS (
    SELECT  (XMLtype(pint.transportdata, nls_charset_id('AL32UTF8')))
    , PINT.PAYMENTINTERCHANGEKEY
  from bph_owner.paymentinterchange pint
  where         PINT.TRANSPORTTIME >= to_date('2024-01-11 00:00:00', 'yyyy-mm-dd hh24:mi:Ss')
       AND  PINT.TRANSPORTTIME < to_date('2024-04-12 00:00:00', 'yyyy-mm-dd hh24:mi:Ss')
       AND  LENGTH(pint.transportdata)>0
       AND PINT.FILEFORMAT like 'pain%'
  )
    SELECT  C1.column_value , q1.Key from q1,
  XMLTABLE(
     '//*'
           PASSING q1.Tdata
              )   C1
  --where regexp_count( C1.column_value,'<') < 2
      ;

哪个有效 - 示例输出:

COLUMN_VALUE
<Id xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02"><PrvtId><Othr><Id>IE57ZZZ05327119</Id><SchmeNm><Prtry>SEPA</Prtry></SchmeNm>/Othr></PrvtId></Id>
<PrvtId xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02"><Othr><Id>IE57ZZZ05327119</Id><SchmeNm><Prtry>SEPA</Prtry></SchmeNm>/Othr>/PrvtId>
<Othr xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02"><Id>IE57ZZZ05327119</Id><SchmeNm><Prtry>SEPA</Prtry></SchmeNm></Othr>
<Id xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02">IE57ZZZ05327119</Id>
<SchmeNm xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02"><Prtry>SEPA</Prtry></SchmeNm>
<Prtry xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02">SEPA</Prtry>

但是如果我尝试使用

REGEXP_COUNT
它会给出:

ORA-19011: Character string buffer too small

如果我将谓词缩减到更小的日期范围,我就能让它发挥作用:

COLUMN_VALUE
<FinInstnId xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02"/>

知道如何让它在更大的日期范围内工作吗?

sql regex xml count oracle19c
2个回答
1
投票

您的过滤器:

where regexp_count( C1.column_value,'<') < 2

似乎与不包含文本的 XML 的叶元素相匹配。

如果这就是您所追求的逻辑,那么就不要使用正则表达式;解析 XML 时,直接在 XPath 表达式中搜索这些条件。

//*[not(*)]
将查找没有子元素的元素,
//*[not(text())]
将查找没有文本的元素,您可以将它们组合为
//*[not(*)][not(text())]
:

SELECT  C1.column_value,
        p.paymentinterchangekey AS Key
FROM    /*bph_owner.*/paymentinterchange p
        CROSS JOIN XMLTABLE(
          '//*[not(*)][not(text())]'
           PASSING XMLtype(p.transportdata)
        ) C1
WHERE   p.TRANSPORTTIME >= DATE '2024-01-11'
AND     p.TRANSPORTTIME <  DATE '2024-04-12'
AND     LENGTH(p.transportdata)>0
AND     p.FILEFORMAT like 'pain%';

对于样本数据:

CREATE TABLE paymentinterchange (
  transportdata,
  paymentinterchangekey,
  transporttime,
  fileformat
) AS
SELECT EMPTY_CLOB() || '<Id xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02"><PrvtId><Othr><Id>IE57ZZZ05327119</Id><SchmeNm><Prtry>SEPA</Prtry></SchmeNm></Othr></PrvtId></Id>',
       1,
       DATE '2024-01-11',
       'paint'
FROM   DUAL UNION ALL
SELECT EMPTY_CLOB() || '<FinInstnId xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02"/>',
       2,
       DATE '2024-01-11',
       'paint'
FROM   DUAL;

输出:

COLUMN_VALUE 钥匙
2

小提琴


0
投票

C1.column_value
(隐式)是一个 XMLType。您将其传递给
regexp_count()
需要一个字符值。这意味着您的 XMLType 已隐式转换,并且默认情况下将使用
getstringval()

要将其作为 CLOB 传入,请显式转换它:

regexp_count( C1.column_value.getclobval(),'<')

但是无论如何都不要这样做;按照@MT0所说的去做...

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