Oracle文本搜索多个表和联接

时间:2013-10-20 10:44:55

标签: sql oracle oracle10g lexer oracle-text

我有以下SQL语句。

select emp_no,dob,dept_no from v_depts
where catsearch (emp_no,'abc',NULL) > 0
or
catsearch (dept_no,'abc',NULL) > 0

其中v_depts是一个视图。

现在我想添加一个或多个表作为连接,以便我可以对列进行文本搜索 例如employee_details包含员工信息,我可以加入emp_no

我在employee_details列的emp_name列上创建了索引,但我无法使用v_depts加入搜索,因为我将我的sql语句修改为

select a.emp_no,a.dob,a.dept_no from v_depts a left outer join employee_details b
on (a.emp_no = b.emp_no)
where catsearch (a.emp_no,'abc',NULL) > 0
or
catsearch (a.dept_no,'abc',NULL) > 0
or
catsearch (b.emp_name,'abc',NULL) > 0

它给了我错误

ORA-20000: Oracle Text error:
DRG-10849: catsearch does not support functional invocation
DRG-10599: column is not indexed

即使我在employee_details表中为emp_name列创建了索引。我怎么解决这个问题?

emp_name的索引声明

CREATE INDEX IDX_EMP_DETAILS ON EMPLOYEE_DETAILS(EMP_NAME)INDEXTYPE IS CTXSYS.CTXCAT

1 个答案:

答案 0 :(得分:4)

我通常通过实现它们的结构化XML视图然后在整个XML上创建索引来解决不同表上多个列的全文搜索。

此解决方案是通用的,也为您提供搜索自由:整个视图或仅一个子路径。缺点是管理通常无法快速刷新的MV的刷新;但是全文索引的更新通常也不是实时的,所以你可以只安排它。

-- Crating the view
CREATE MATERIALIZED VIEW fulltext_helper
NOLOGGING
BUILD DEFERRED
REFRESH COMPLETE ON DEMAND
AS
SELECT 
   a.dob, -- we don't need to fulltext on him
   XMLELEMENT(helper,
     XMLFOREST(a.emp_no AS emp_no, 
              a.dept_no AS dept_no, 
              b.emp_name AS emp_name)
   ) AS indexme
FROM v_depts a 
LEFT OUTER JOIN employee_details b
ON (a.emp_no = b.emp_no);

-- Creating the index
BEGIN
    ctx_ddl.create_preference('fulltext_helper_lexer', 'BASIC_LEXER');
    ctx_ddl.create_preference('fulltext_helper_filter', 'NULL_FILTER');
END;
/
CREATE INDEX fulltext_helper_index ON fulltext_helper (indexme)
INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS (
    'DATASTORE CTXSYS.DIRECT_DATASTORE
     LEXER fulltext_helper_lexer
     FILTER fulltext_helper_filter');

-- Searching the whole data
SELECT * FROM fulltext_helper
WHERE contains(indexme, '{abc} INPATH (/helper)') > 0;

-- Searching only on "empno"
SELECT * FROM fulltext_helper
WHERE contains(indexme, '{abc} INPATH (/helper/emp_no)') > 0;