我有以下 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 |
---|
|
|
|
|
|
|
但是如果我尝试使用
REGEXP_COUNT
它会给出:
ORA-19011: Character string buffer too small
如果我将谓词缩减到更小的日期范围,我就能让它发挥作用:
COLUMN_VALUE |
---|
|
知道如何让它在更大的日期范围内工作吗?
您的过滤器:
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 |
C1.column_value
(隐式)是一个 XMLType。您将其传递给 regexp_count()
, 需要一个字符值。这意味着您的 XMLType 已隐式转换,并且默认情况下将使用 getstringval()
。
要将其作为 CLOB 传入,请显式转换它:
regexp_count( C1.column_value.getclobval(),'<')
但是无论如何都不要这样做;按照@MT0所说的去做...