从 CLOB ListAgg 值中删除 Oracle SQL 中的 HTML 代码

Posted

技术标签:

【中文标题】从 CLOB ListAgg 值中删除 Oracle SQL 中的 HTML 代码【英文标题】:Removing HTML Code in Oracle SQL from a CLOB ListAgg value 【发布时间】:2019-05-14 10:32:09 【问题描述】:

我有一些代码可以恢复标准列,但随后有一些列使用 Listagg 函数将多个值放入 1 个单元格而不是多行。名为“Notes”的列将任何注释存储为“CLOB”

问题是当组织内的某个人将电子邮件另存为便笺时。当报告运行时,它会输出包含在 html 标签中的电子邮件内容(以及很多标签)

我想从输出中删除所有 html 标记,只留下纯文本,而不管注释或格式如何。

如果单元格的格式不是 clob,则这段代码可以正常工作:

REGEXP_REPLACE(COLUMN_NAME,'\s*<[^>]*>\s*',NULL,1,0,'im')

但它不会对我的代码产生的输出做任何事情。

我处理 listagg 并产生 CLOB 输出的代码是:

Note_data_main AS(
SELECT DISTINCT
AI.INVOICE_ID,
AI.INVOICE_NUM,
note.*,
NULL AS ORG_ID,
NULL As Invoice_Date, 
NULL AS HOLD_REASON, 
NULL AS RELEASE_REASON, 
NULL AS Hold_Date, 
NULL AS VENDOR_NAME,  
NULL AS VENDOR_SITE_CODE,
NULL AS Due_Date,
NULL AS DAYS_OVERDUE,
NULL AS SEGMENT1,
NULL AS Days,
NULL AS Requisitioner,
NULL AS CreatedName,
NULL AS Overdue_Status

FROM
AP_INVOICES_ALL AI,
zmm_notes note
WHERE
AI.INVOICE_ID = note.SOURCE_OBJECT_UID(+)

),

JOINAGE AS (
SELECT A.*, DBMS_LOB.SUBSTR(B.NOTE_TXT,30000) AS Note
FROM INVOICE_DATA A
LEFT JOIN Note_data_main B
ON A.INVOICE_ID = B.SOURCE_OBJECT_UID
),
NOTEDEET AS (

SELECT INVOICE_ID,ORG_ID,INVOICE_NUM,INVOICE_DATE,
HOLD_REASON,VENDOR_NAME,VENDOR_SITE_CODE,
DUE_DATE,DAYS_OVERDUE,SEGMENT1,DAYS,REQUISITIONER,
CREATEDNAME,OVERDUE_STATUS,
rtrim(xmlagg(xmlelement(e, Note, (chr(10)||'--------------- 
'||chr(10)))).extract('//text()').getclobval(), (chr(10)||'--------------- 
'||chr(10))) AS Notes
FROM 
JOINAGE
GROUP BY 
INVOICE_ID,ORG_ID,INVOICE_NUM,INVOICE_DATE,HOLD_REASON,VENDOR_NAME,
VENDOR_SITE_CODE,DUE_DATE,DAYS_OVERDUE,SEGMENT1,DAYS,
REQUISITIONER,CREATEDNAME,OVERDUE_STATUS
ORDER BY INVOICE_ID
)

以下是当前输出和我想要实现的目标 当前:

<p><font face="Times New Roman" size="3">

</font></p><p style="margin: 0cm 0cm 0pt;"><font 
face="Arial,Helvetica,sans-serif" size="3">Good
afternoon Inspector XXX</font></p><p><font face="Arial,Helvetica,sans- 
serif" size="3">

</font></p><p style="margin: 0cm 0cm 0pt;"><font 
face="Arial,Helvetica,sans-serif" size="3"><span style="color: rgb(31, 73, 
125);"><font face="Arial,Helvetica,sans-serif" size="3">We
have received the attached invoice for payment but unfortunately, we are 
unable
to make payment as there is not enough money on the purchase order for 
which
you are the requester.</font></span></font></p><p style="margin: 0cm 0cm 
0pt;"><font face="Arial,Helvetica,sans-serif" size="3"><span style="color: 
rgb(31, 73, 125);"><br/></span></font>

预期:

"

不错 下午督察XXX

我们 已收到随附的付款发票,但很遗憾,我们无法 付款,因为采购订单上没有足够的钱 你是请求者。"

我知道创建函数可以处理这种情况,但我正在使用 Oracle BI Cloud,因此我无法插入和创建表并创建任何函数以供以后调用。

非常感谢任何帮助,如果您需要更多信息,请告诉我。

【问题讨论】:

您似乎使用的是xmlagg而不是listagg,这有点令人困惑。更重要的是,您还没有展示如何将regexp_replace 应用于您的查询。将您的示例电子邮件视为 VARCHAR2 或 CLOB 字符串会得到相同的结果 - 不是您想要的,因为换行符已关闭,但它不会执行 nothing。听起来您正在尝试对聚合结果执行此操作 - 为什么不将其直接应用于 Note在聚合之前 当我在最终选择中使用正则表达式时,它没有删除任何内容,因此 (Select regexp_replace(notes,,'<.>') as Notes from NOTEDEET 似乎没有删除任何内容。我已经接受了您的建议并将正则表达式向上移动并将其用于列并且它有效。它是如此简单但感谢您帮助它。就像你说的那样,休息时间已经关闭并且仍然存在于输出中,但这应该是通过添加到正则表达式很容易删除。 【参考方案1】:

在 Alex Poole 的帮助下,解决方案将 regex_replace 放在代码的前面,以便直接影响列

这是我改变的:

JOINAGE AS (
SELECT A.*, regexp_replace(regexp_replace(DBMS_LOB.SUBSTR(B.NOTE_TXT,30000),'<.*?>'),'&nbsp') AS Note
FROM INVOICE_DATA A
LEFT JOIN Note_data_main B
ON A.INVOICE_ID = B.SOURCE_OBJECT_UID
)

【讨论】:

以上是关于从 CLOB ListAgg 值中删除 Oracle SQL 中的 HTML 代码的主要内容,如果未能解决你的问题,请参考以下文章

用listagg怎么替代这个写法

oracle listagg的 截取长度限制有没有啥方法解决

Oracle SQL:如何删除 listagg 中的重复项

listagg:删除相邻的重复项

从datagridview值中删除数据库中的行

如何从 ValueListBox 值中删除空值