我正在尝试运行以下查询来浏览一堆包含HTML页面的CLOB:
SELECT template_id, REGEXP_SUBSTR(clean_html, 'src="[^"]*\.js"', 1, LEVEL, 'i') AS match
FROM (
SELECT template_id, REGEXP_REPLACE(html_text, '<!--.*?-->', '', 1, 0, 'n') AS clean_html
FROM (
SELECT t.id as template_id, dbms_lob.substr(t.data, 4000, 1) AS html_text
FROM template t
)
)
CONNECT BY REGEXP_SUBSTR(clean_html, 'src="[^"]*\.js"', 1, LEVEL, 'i') IS NOT NULL
GROUP BY template_id,
clean_html,
LEVEL
order by 1
但是我在第1行和第34行的字符串缓冲区太小了。几乎是在运行我的查询后直接。
如果我在一个只有几个模板的小数据集上运行它,那么一旦我在整个HTML模板列表上运行它,它就会抛出错误。
我认为这个问题与dbms_lob.substr(data,4000,1)有关,可能与子字符串超过4000字节有关,因为隐藏字符(或其他东西?),但我不知道知道如何解决它。
如果我写dbms_lob.substr(data,2000,1),那么我的子字符串太小,我丢失了HTML文件中的重要数据。如果我把它大于4000那么我会立即得到#34;缓冲区太小&#34;错误。
任何人都知道如何解决这个问题?理想情况下,我想查看我的整个数据&#39;字段而不仅仅是前4000个字符。但是,如果它在我长长的HTML文件列表中工作,那么前4000个字符就可以了。
谢谢
答案 0 :(得分:0)
我假设您正在使用GROUP BY
来获取不同的值,对吗?在这里对许多记录使用CONNECT BY
的问题是它将返回大量重复项。但GROUP BY
和DISTINCT
不是处理此问题的正确方法。取出GROUP BY
并将以下行附加到您的查询中:
AND PRIOR template_id = template_id
AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL
另外,我认为您希望在最里面的查询中添加以下条件:
WHERE REGEXP_LIKE(t.data, 'src="[^"]*\.js"', 'i')
否则,查询将始终为template_id
的每个值返回至少一行。
我不太确定CLOB发生了什么,但我还没能完全重现你的错误。
<强> EDITED 强>
我想我有一个解决方案。请尝试以下方法:
SELECT template_id, REGEXP_SUBSTR(clean_html, 'src="[^"]*\.js"', 1, LEVEL, 'i') AS match
FROM (
SELECT template_id, REGEXP_REPLACE(html_text, '<!--.*?-->', '', 1, 0, 'n') AS clean_html
FROM (
SELECT t.id as template_id, t.data AS html_text
FROM template t
WHERE REGEXP_LIKE(t.data, 'src="[^"]*\.js"', 'i')
)
)
CONNECT BY TO_CHAR(REGEXP_SUBSTR(clean_html, 'src="[^"]*\.js"', 1, LEVEL, 'i')) IS NOT NULL
AND PRIOR template_id = template_id
AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL;
我认为问题在于CONNECT BY
子句
CONNECT BY REGEXP_SUBSTR(clean_html, 'src="[^"]*\.js"', 1, LEVEL, 'i') IS NOT NULL
此处比较CHAR
比CLOB
更好:
CONNECT BY TO_CHAR(REGEXP_SUBSTR(clean_html, 'src="[^"]*\.js"', 1, LEVEL, 'i')) IS NOT NULL
你甚至可以在这里使用DBMS_LOB.SUBSTR()
安全:
CONNECT BY DBMS_LOB.SUBSTR(REGEXP_SUBSTR(clean_html, 'src="[^"]*\.js"', 1, LEVEL, 'i'), 4000, 1) IS NOT NULL
最后,我认为你不需要那么多级别的子查询。我想你可以做到以下几点:
SELECT template_id, REGEXP_SUBSTR(clean_html, 'src="[^"]*\.js"', 1, LEVEL, 'i') AS match
FROM (
SELECT t.id AS template_id, REGEXP_REPLACE(t.data, '<!--.*?-->', '', 1, 0, 'n') AS clean_html
FROM template t
WHERE REGEXP_LIKE(t.data, 'src="[^"]*\.js"', 'i')
)
CONNECT BY DBMS_LOB.SUBSTR(REGEXP_SUBSTR(clean_html, 'src="[^"]*\.js"', 1, LEVEL, 'i'), 4000, 1) IS NOT NULL
AND PRIOR template_id = template_id
AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL;
希望这有帮助。