Oracle:跨越多列的“grep”?

时间:2010-01-29 09:36:41

标签: sql oracle grep

我想在多个列中执行likeregexp。这些列包含标签,关键字等等等于:

sqlplus scott/tiger @myquery.sql | grep somestring

现在我有类似

的东西
select * from foo where c1 || c2 || c3  like '%somestring%'

但我希望我能得到一些更通用和/或优化的东西。任何线索都赞赏!

5 个答案:

答案 0 :(得分:3)

在11G上你可以创建一个虚拟列:

alter table foo add all_text varchar2(4000) generated always as (c1 ||','|| c2 ||','|| c3);

(见Oracle 11G new features)。

然后查询:

select * from foo where all_text like '%somestring%'

你可以在all_text上添加一个索引,如果它也有助于提高性能(请参阅this answer了解它何时可以提供帮助,何时没有)。

在11G之前,您可以做同样的事情,但是使用正常的列,通过触发器维护。

答案 1 :(得分:3)

您是否考虑过使用Oracle Text的连锁数据存储功能?

Oracle Text允许您在同一个表中的多个列上创建全文索引。或者至少有一个过程可以做到这一点。

我之前使用的Oracle网站上有一个很好的示例文档:

http://www.oracle.com/technology/sample_code/products/text/htdocs/concatenated_text_datastore/cdstore_readme.html

Oracle Text搜索速度非常快。我想我会考虑在每个列上保留单独的上下文索引,以便您可以为每个列匹配应用相关性和优先级。

如果您想要一个例子,请告诉我,我会在答案中添加一些内容。

希望这有帮助。

答案 2 :(得分:1)

作为顾问,我经常不得不在文档记录不佳的数据库中进行搜索,并且需要一些方便的脚本来查找数据。这是两个示例,该示例如何生成一个select子句来搜索表中所有“ VARCHAR2”列中的数据:

示例1。搜索字符串的一部分:

SELECT 'SELECT * FROM ' || min(TABLE_NAME) ||' WHERE ' || LISTAGG(COLUMN_NAME, ' like ''%somestring%'' or ') WITHIN GROUP (ORDER BY COLUMN_ID) || ' like ''%somestring%'';' 
from ALL_TAB_COLUMNS
WHERE OWNER = 'YOUR_SCHEMA_NAME' -- Uppercase
AND TABLE_NAME = 'YOUR_TABLE_NAME' --Uppercase
AND DATA_TYPE LIKE 'VARCHAR2';

示例2。搜索整个值:

SELECT 'SELECT * FROM ' || min(TABLE_NAME) ||' WHERE ''somestring'' in (' || LISTAGG(COLUMN_NAME, ', ') WITHIN GROUP (ORDER BY COLUMN_ID) || ');' 
from ALL_TAB_COLUMNS
WHERE OWNER = 'YOUR_SCHEMA_NAME' -- Uppercase
AND TABLE_NAME = 'YOUR_TABLE_NAME' --Uppercase
AND DATA_TYPE LIKE 'VARCHAR2';

答案 3 :(得分:0)

答案 4 :(得分:0)

SELECT * FROM table WHERE REGEXP_LIKE(col1, <pattern>)
union
SELECT * FROM table WHERE REGEXP_LIKE(col2, <pattern>)
union
SELECT * FROM table WHERE REGEXP_LIKE(col3, <pattern>)

这应该有效。但我怀疑这是否会比你的查询更好。你可能想要比较两者的表现。真的很想听听你的发现。 : - )