【问题标题】:Oracle Contains search with ApostropeOracle 包含带撇号的搜索
【发布时间】:2018-12-13 10:37:11
【问题描述】:

我使用的是 Oracle 11g,我有一个名为 test 的表,其中包含 firstname 和 lastname 列。

  1. firstname 列包含 D'Arch
  2. Lastname 列包含 O'Neil

我的索引结合了firstname 和lastname 列,我正在使用CONTAINS (firstname, '%'|| 'D''A' ||'%') >0

Oracle 查询是

select * 
from test 
where CONTAINS (firstname, '%'|| 'D''Ar' ||'%') >0

但是结果集是空的。 Oracle Like 和 instr 关键字工作正常,但我不想更改现有的实现。

对此问题的任何建议。

【问题讨论】:

  • 检查你的词法分析器的定义。撇号很可能定义为 skipjoin,但必须定义为 printjoin 才能启用搜索。

标签: oracle oracle11g


【解决方案1】:

假设这些样本数据 - 请参阅下面的 CTAS 语句来创建它们。

FIRSTNAME LASTNAME
--------- --------
D'Arch    O'Neil   
DArch     ONeil    
D Arch    O Neil   
D.Arch    O.Neil 

要保留撇号,您必须将其定义为printjoin 字符。否则将在分词过程中被删除(与最后一行中的点比较)。

BEGIN
  ctxsys.ctx_ddl.create_preference('lex', 'BASIC_LEXER');
  ctxsys.ctx_ddl.set_attribute('lex', 'printjoins', '''');  
END;
/
---
BEGIN
  ctxsys.ctx_ddl.create_preference('pref', 'MULTI_COLUMN_DATASTORE');
  ctx_ddl.set_attribute('pref', 'columns', 'firstname, lastname');
END;
/

create index idx_test on test(firstname)
indextype is CTXSYS.CONTEXT
parameters ('datastore  pref LEXER  lex')
;

创建索引后查看结果tokes的最佳方法是查询包含所有tokes的$I表:

select TOKEN_TEXT from DR$IDX_TEST$I;

TOKEN_TEXT                                                     
----------------------------------------------------------------
ARCH                                                             
D'ARCH                                                           
DARCH                                                            
FIRSTNAME                                                        
LASTNAME                                                         
NEIL                                                             
O                                                                
O'NEIL                                                           
ONEIL                                                            

正如预期的那样,点消失了,但撇号仍然存在。

现在你可以查询并且得到预期的结果:

select * 
from test 
where CONTAINS (firstname, '%D''Ar%') >0;

FIRSTNAME LASTNAME
--------- --------
D'Arch    O'Neil 

当然,当您使用MULTI_COLUMN_DATASTORE 时,您还可以查询lastname 列中的数据。

select * 
from test 
where CONTAINS (firstname, '%O''Ne%') >0;

FIRSTNAME LASTNAME
--------- --------
D'Arch    O'Neil

样本数据

create table test as
select 'D''Arch' firstname, 'O''Neil' Lastname from dual union all
select 'DArch' firstname, 'ONeil' Lastname from dual union all
select 'D Arch' firstname, 'O Neil' Lastname from dual union all
select 'D.Arch' firstname, 'O.Neil' Lastname from dual;

【讨论】:

  • 谢谢,但我已经在这个名字列上有了 mutlistore 索引。在运行新索引时,它说“无法使用相同的索引类型在列列表上创建多个域索引”
  • 删除现有索引并重新创建后..这很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多