从CLOB列提取匹配模式返回重复行,如何获取唯一行?
问题分析与解决
重复行产生的原因
- 递归无行关联约束:你的查询没有指定递归时父行与子行的关联条件,当
test表存在多行数据时,每一行都会被递归展开,不同行的递归结果交叉组合,产生大量重复行。 - 缺少防循环控制:未添加防止递归循环的条件,可能导致同一行被重复递归处理。
- 正则匹配逻辑问题:当前
REGEXP_SUBSTR返回的是整个匹配串(包含IS:</u><BR>和结尾的<BR><BR>),而非目标内容,可能导致后续无法正确识别唯一值;另外REGEXP_COUNT返回3但实际有5条数据,说明正则模式未覆盖所有目标匹配项,需要校验模式准确性。
解决方法
步骤1:修正递归逻辑并提取目标内容
添加行唯一标识(如ROWID或表主键)到CONNECT BY中,限制递归仅针对当前行展开,同时调整REGEXP_SUBSTR提取正则分组内的目标内容:
SELECT DISTINCT REGEXP_SUBSTR(des, 'IS:</u><BR>(.*?)<BR><BR>', 1, LEVEL, 'i', 1) AS name FROM test CONNECT BY LEVEL <= REGEXP_COUNT(des, 'IS:</u><BR>(.*?)<BR><BR>', 1, 'i') AND PRIOR ROWID = ROWID AND PRIOR SYS_GUID() IS NOT NULL;
关键说明:
REGEXP_SUBSTR的第6个参数1:提取正则中(.*?)匹配的分组内容,直接得到目标值而非整个匹配串。DISTINCT:过滤掉因正则匹配或递归产生的重复行。PRIOR ROWID = ROWID:确保递归仅针对当前行展开,避免不同行的结果交叉重复。PRIOR SYS_GUID() IS NOT NULL:Oracle中防止递归循环的常用技巧,通过唯一值避免循环递归。
步骤2:校验并调整正则模式
如果REGEXP_COUNT返回结果与实际不符,需调整正则模式覆盖所有场景:
- 添加
'i'参数忽略大小写匹配。 - 用
\s*匹配可能存在的空格、换行等特殊字符:REGEXP_COUNT(des, 'IS:</u>\s*<BR>\s*(.*?)\s*<BR>\s*<BR>', 1, 'i')
内容的提问来源于stack exchange,提问作者APR
相关产品推荐
相关产品推荐

