如何检查多行注释是否含特定单词?及用all_source搜索代码时忽略多行注释
处理all_source表中多行注释的搜索需求
一、检查多行注释中是否包含特定单词
Oracle的多行注释以/*开头、*/结尾,往往会跨占all_source的多条行记录。要检测这类注释里的目标单词,得先把属于同一块注释的行拼接起来,再做匹配:
WITH source_comment_state AS ( SELECT owner, name, type, line, text, -- 计算当前行的注释嵌套深度:1及以上表示处于注释内 SUM( CASE WHEN INSTR(text, '/*') > 0 THEN 1 ELSE 0 END - CASE WHEN INSTR(text, '*/') > 0 THEN 1 ELSE 0 END ) OVER (PARTITION BY owner, name, type ORDER BY line ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS comment_depth FROM all_source ), comment_blocks AS ( SELECT owner, name, type, -- 把同一块注释的所有行文本拼接起来 LISTAGG(text, ' ') WITHIN GROUP (ORDER BY line) AS full_comment FROM source_comment_state WHERE comment_depth > 0 -- 按注释块分组:用之前的非注释行数作为分组标识,区分不同的注释块 GROUP BY owner, name, type, SUM(CASE WHEN comment_depth = 0 THEN 1 ELSE 0 END) OVER (PARTITION BY owner, name, type ORDER BY line ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) ) SELECT * FROM comment_blocks WHERE REGEXP_LIKE(full_comment, '(^|\s)SOME_WORD(\s|$)');
这段SQL先标记每行是否处于注释内,再把同一块注释的行拼接成完整文本,最后在完整注释里搜索目标单词,连跨行的注释也能覆盖。
二、搜索时忽略多行注释内的文本
要实现这个,得先把代码里的所有多行注释内容剔除,再对清理后的代码做原有的单词搜索:
WITH source_cleanup AS ( SELECT owner, name, type, line, -- 根据当前行的注释状态,裁剪掉注释部分 CASE WHEN prev_comment_depth > 0 THEN -- 当前行在注释内,只保留*/之后的内容 SUBSTR(text, INSTR(text, '*/') + 2) ELSE -- 当前行不在注释内,只保留/*之前的内容 SUBSTR(text, 1, INSTR(text, '/*') - 1) END AS cleaned_text, -- 更新注释深度,供下一行使用 prev_comment_depth + CASE WHEN INSTR(text, '/*') > 0 THEN 1 ELSE 0 END - CASE WHEN INSTR(text, '*/') > 0 THEN 1 ELSE 0 END AS curr_comment_depth FROM ( SELECT *, -- 计算当前行之前的注释深度 NVL(SUM( CASE WHEN INSTR(text, '/*') > 0 THEN 1 ELSE 0 END - CASE WHEN INSTR(text, '*/') > 0 THEN 1 ELSE 0 END ) OVER (PARTITION BY owner, name, type ORDER BY line ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING), 0) AS prev_comment_depth FROM all_source ) t ), cleaned_code_lines AS ( SELECT owner, name, type, line, TRIM(cleaned_text) AS code_line FROM source_cleanup WHERE cleaned_text IS NOT NULL AND TRIM(cleaned_text) != '' ) SELECT * FROM cleaned_code_lines WHERE REGEXP_LIKE(code_line, '(^|\s)SOME_WORD(\s|$)');
这段SQL会逐行判断是否处于注释内,自动裁剪掉注释部分,只保留有效代码,最后在干净的代码里搜索目标单词,完全忽略多行注释里的内容。如果有嵌套注释(比如/* 外层注释 /* 内层注释 */ 外层注释 */),注释深度的计算也能正确处理。
内容的提问来源于stack exchange,提问作者DZN
相关产品推荐
相关产品推荐

