2015-05-12 5 views
27

Chcę mieć możliwość uniknięcia kryteriów wyszukiwania w zapytaniu tekstowym Oracle za pomocą contains i połączenia kryteriów z symbolem wieloznacznym, aby uzyskać kryteria "podwójnie okrojone". (Wiem, że moje indeksy mogą nie być skonfigurowane dla idealnej wydajności, ale to jest zbyteczne). Chcę mieć możliwość używania składni nawiasów klamrowych dla lepszej czytelności, ale to nie działa. Zgodnie z najlepszą odpowiedzią na to powiązane (ale nie zduplikowane) pytanie, nawiasy klamrowe definiują pełne tokeny. Czy istnieje sposób wyłączenia lub obejścia tego zachowania?Odsyłanie tekstu Oracle za pomocą nawiasów klamrowych i symboli wieloznacznych

Oracle Text: How to sanitize user input

wolałbym uniknąć konieczności ucieczki każdy pojedynczy znak w moich kryteriów (zgodnie z ostatnim wybierz w moim kodu) lub spróbuj wyszukać ciąg dla znaków specjalnych, ponieważ zarezerwowane słowa są również uważane za „specjalne ". (Zauważ, że nie mam słów zatrzymania) Poniższe ilustruje mój problem. (Niestety SQLFiddle nie wydaje się wspierać tekst Oracle):

create table MY_TABLE(MY_COL varchar2(20)); 
insert into MY_TABLE(MY_COL) values ('abc'); 
insert into MY_TABLE(MY_COL) values ('abcd'); 
insert into MY_TABLE(MY_COL) values ('abcde'); 
insert into MY_TABLE(MY_COL) values ('bcd'); 
insert into MY_TABLE(MY_COL) values ('bcde'); 

create index FTIX on MY_TABLE (MY_COL) 
indextype is CTXSYS.CONTEXT 
PARAMETERS ('STOPLIST CTXSYS.EMPTY_STOPLIST SYNC (ON COMMIT)'); 

select * from MY_TABLE where CONTAINS(MY_COL, '%bcd%') > 0; --expected results 
select * from MY_TABLE where CONTAINS(MY_COL, '%{bcd}%') > 0; --no results 
select * from MY_TABLE where CONTAINS(MY_COL, '{bcd}') > 0; --returns bcd 
select * from MY_TABLE where CONTAINS(MY_COL, '{%bcd%}') > 0; --returns bcd 
select * from MY_TABLE where CONTAINS(MY_COL, '%\b\c\d%') > 0; --expected results 
+2

Miło Cię widzieć pod warunkiem utworzyć i wstawić sprawozdań, coś, co nie jest zazwyczaj postrzegane na przepełnienie stosu. +1 za to! –

+1

Czy możesz skonstruować ciąg wyszukiwania w funkcji użytkownika, abyś miał coś w rodzaju 'wybierz * z MY_TABLE, gdzie ZAWIERA (MY_COL, DoubleEscape ('bcd'))> 0', gdzie DoubleEscape jest nazwą twojej funkcji? W funkcji pętli po prostu ciąg i uciekaj od wszystkiego. – johnjps111

Odpowiedz

3

Jak o:

select * from MY_TABLE where CONTAINS(MY_COL, regexp_replace('*abc*', '([^*])', '\\\1')) > 0 
+0

Użyję tego w porównaniu z moim obecnym podejściem, jednak szukałem czegoś w silniku pełnego tekstu, zamiast "hackowania wstępnego". Mogę zrobić to samo w moim kodzie lub przesłać go do Oracle równie łatwo. – Necreaux

+0

poprawiona ponownie w celu usunięcia niepotrzebnej dyskusji – johnjps111

+0

Próbowałem wprowadzić podejście z nawiasami klamrowymi. Uciekanie jest zwykle niepotrzebne w połączeniu z symbolami wieloznacznymi. Stąd, dla tytułu "morze w ziemi", możesz zrobić "ZAWIERA (title,"% ea {within} {the} ear% ')> 0; '. Sygnał wejściowy potencjalnie można dezynfekować przed wykonaniem tej czynności, usuwając znaki niealfabetyczne, które są traktowane jako białe znaki przez BASIC_LEXER. Jednak staje się to skomplikowane/łamie się, gdy rozważamy pytanie, co to są znaki niealfabetyczne. Znaki akcentowane są indeksowane. Proponowane podejście polegające na ucieczce od każdej postaci jest w rzeczywistości prostsze i działa lepiej. – DKroot