Как обойти ограничение text_query на 4000 символов в операторе Oracle CONTAINS?

В Oracle синтаксис полнотекстового поиска содержит оператор:

 CONTAINS(
          [schema.]column,
          text_query    VARCHAR2
          [,label       NUMBER]) RETURN NUMBER;

что означает, что text_query не может быть длиннее 4000 символов, иначе произойдет ошибка. Во многих случаях я неоднократно использовал text_query длиной более 4000 символов. Как бы вы, как эксперт Oracle, предложили обойти это ограничение, если это возможно?

Чтобы еще больше прояснить ситуацию, в которой 4000 легко достигается, это то, что если вы объедините много Содержит операторы запросов для построения вашего text_query, вполне возможно превысить такое ограничение в 4000 символов.


person hko19    schedule 25.06.2010    source источник
comment
Ограничение столбца таблицы VARCHAR2 составляет 4000 символов, но ограничение переменной VARCHAR2 в PL/SQL составляет 32767 символов. Вы уверены, что текстовый запрос в операторе CONTAINS ограничен 4000, а не 32767?   -  person Mark Baker    schedule 25.06.2010
comment
@MarkBaker - CONTAINS() - это функция SQL, поэтому применяется ограничение SQL.   -  person APC    schedule 25.06.2010
comment
@APC Спасибо за разъяснения, я никогда не использовал текстовые индексы Oracle, поэтому я не был уверен   -  person Mark Baker    schedule 25.06.2010


Ответы (2)


Ограничение в 4000 символов не является какой-то произвольной границей: это максимальное количество символов VARCHAR2, которое может обрабатывать Oracle SQL.

4000 символов — это много текста. На английском языке это около 600 слов, или страница формата А4, и немного шрифта приемлемого размера. Я не могу придумать много приложений, которые требуют поиска таких больших кусков словоблудия. Даже колледжи, проверяющие сочинения студентов на предмет плагиата, будут работать не более чем на уровне абзаца.

Однако, если у вас действительно есть ситуация, в которой сопоставление скудных 4000 символов приводит к ложным срабатываниям, все, что вы можете сделать, это разбить строку запроса на куски и выполнить поиск по ним. Это означает, что вы должны использовать PL/SQL:

create or replace function big_search (p_search_text in varchar2) 
    return sys_refcursor
is
    return_value sys_refcursor;
    p_srch1 varchar2(4000);
    p_srch2 varchar2(4000);
begin

    dbms_output.put_line('search_length='||to_char(length(p_search_text)));

    p_srch1 := substr(p_search_text, 1, 4000);
    p_srch2 := substr(p_search_text, 4001, 4000);


    open return_value for 
        select docname
                , (score(1) + score(2))/2 as score
        from t23
        where contains ( text_column, p_srch1 , 1) != 0
        and  contains ( text_column, p_srch2 , 2) != 0;

    return return_value;
end;
/

Если вы заранее не знаете размер искомого текста, вам нужно будет использовать динамический SQL для его сборки. Обратите внимание, что передача пустых условий поиска в CONTAINS() приведет к выбрасыванию DRG-50901: text query parser syntax error.

person APC    schedule 25.06.2010
comment
+1 Я думал о том же, но у меня нет знаний текстового поиска, чтобы ответить. - person Tony Andrews; 25.06.2010
comment
Ситуация может потребовать динамического SQL, может ли кто-нибудь дать больше указателей? - person hko19; 26.06.2010
comment
Когда приведенный выше поисковый текст динамически создается из различных операторов запроса и его общая длина превышает 4000, представленная логика принудительного разбиения текста запроса на 4000 фрагментов и «и» их вместе приводит к неправильному результату или синтаксической ошибке. - person hko19; 02.07.2010
comment
Вышеупомянутое не работает, потому что код разбивает оператор на произвольные фрагменты - один или несколько фрагментов могут не быть допустимым предложением SQL, что приводит к исключению. - person user481779; 02.02.2012

Текущая версия теперь поддерживает параметр CLOB.

CONTAINS(
     [schema.]column,
     text_query    [VARCHAR2|CLOB]
     [,label       NUMBER])
RETURN NUMBER;

http://docs.oracle.com/cd/B28359_01/text.111/b28304/csql.htm#i997503

person Ophir Yoktan    schedule 28.12.2012