sqloracleoracle10glexeroracle-text

Oracle text search on multiple tables and joins


I have the following SQL statement.

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

where v_depts is a view.

Now I would like to add one or more tables as join so that I can do text search on columns e.g. employee_details contains employee information and I can join with emp_no

I have created index on employee_details table for emp_name column, however I am not able to join with v_depts to search because I modify my sql statement as

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

it gives me error

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

even though I have created index for emp_name column in employee_details table. How can I solve this problem?

Index statement for emp_name

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

Solution

  • I usually solve fulltext searches on multiple columns on different tables by materializing a structured XML view of them and then creating the index on the whole XML.

    This solution is generic and also give you freedom on search: the whole view or only a subpath. The drawback is managing the refresh of a MV who usually cannot be refreshed fast; but update of fulltext index usually isn't in real-time, too, so you can just schedulate it.

    -- 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;