现在的位置: 首页 > 综合 > 正文

Oracle文本查询

2018年05月21日 ⁄ 综合 ⁄ 共 8717字 ⁄ 字号 评论关闭

查询文本不同于查询数据,因为有同义词、近义词和反义词。你可能希望搜索互相接近的词或搜索相关联的词。如果仅使用标准的关系操作符,要进行这些查询是非常困难的。通过SQL进行扩充,使其包含文本索引,则ORACLE TEXT允许用户就文本提出非常复杂的问题。
文本索引主要有两种CONTEXT和CTXCAT

用如下方式建立索引
CREATE INDEX REVIEW_CONTEXT_INDEX ON BOOK_REVIEW_CONTEXT(REVIEW_TEXT) INDEXTYPE IS CTXSYS.CONTEXT;

CREATE INDEX REVIEW_CTXCAT_INDEX ON BOOK_REVIEW_CTXCAT(REVIEW_TEXT) INDEXTYPE IS CTXSYS.CTXCAT;

建立好索引后就可以进行文本查询
select title from book_review_context where contains(review_text,'property')>0
CONTAINS函数有两个参数即列名和搜索串,它检查review_text列的文本索引。如果在review_text列的文本索引中找到单词'property'则数据库返回的得分大于0,并返回匹配的TITLE值。

如果建立的是CTXCAT索引就用CATSEARCH函数
select title from book_review_ctxcat where catsearch(review_text,'property',null)>0;

可使用的文本查询表达式有以下几种:
1。单词的精确匹配搜索
select title from book_review_context where contains(review_text,'property')>0
2。多个单词精确匹配的搜索
可以使用AND连接多个单词
select title from book_review_context where contains(review_text,'property and harvests')>0
还可以使用&但是在SQLPLUS里必须执行set define off否则&将被视作变量
set define off
select title from book_review_context where contains(review_text,'property & harvests')>0
对于CTXCAT索引AND完全可以省略
select title from book_review_ctxcat where catsearch(review_text,'property harvests',null)>0;
除AND外还可以使用OR运算符在ORACLE TEXT中OR是一根竖线(|)
因此下面的两个查询是等同的
select title from book_review_context where contains(review_text,'property or harvests')>0

select title from book_review_context where contains(review_text,'property | harvests')>0
但是要注意CATSEARCH函数不支持OR只支持‘|’符号;
ACCUM(累加)提供了另一种组合搜索的方法。等价于逗号,所以下面的两个查询是等价的
select title from book_review_context where contains(review_text,'property accum harvests')>0
select title from book_review_context where contains(review_text,'property , harvests')>0
但是CATSEARCH函数调用支持ACCUM语法但不应该使用,因为CATSEARCH不计算用来与阀值进行比较的得分;
MINUS运算符从第一项搜索的得分中减去第二项搜索的得分等价于减号,所以下面的两个查询是等价的
select title from book_review_context where contains(review_text,'property minus harvests')>0
select title from book_review_context where contains(review_text,'property - harvests')>0
可以用圆括号来阐明搜索条件内的逻辑
select title from book_review_context where contains(review_text,'house or (workers and harvests')>0
3。短语精确匹配的搜索
在进行短语搜索的时候应将整个短语作为搜索串的一部分
select title from book_review_context where contains(review_text,'doctor visits')>0
若搜索的短语中包含ORACLE TEXT内的保留字,则必须使用花括号括住相应的保留字
select title from book_review_context where contains(review_text,'taengdmg {and} dfdng)>0
4。搜索互相接近的词
select title from book_review_context where contains(review_text,'property near harvests')>0
可以使用关键词NEAR也可以用;代替NEAR
5。在搜索中使用通配符
select title from book_review_context where contains(review_text,'worker%')>0
select title from book_review_context where contains(review_text,'work___)>0
6。搜索具有相同词根的词
select title from book_review_context where contains(review_text,'$worker')>0
7。模糊匹配搜索
select title from book_review_context where contains(review_text,'?worker')>0
8。搜索发音相似的词
select title from book_review_context where contains(review_text,'!worker')>0
9。使用ABOUT运算符
在ORACLE TEXT中可以搜索文档的主题
select review_text from book_review_context where contains(review_text,'about(mdgd)')>0
10。索引集
为了建立一个名为reviews的索引集可使用CREATE_INDEX_SET过程
execute ctx_ddl.create_index_set('reviews)
可以通过add_index过程添加索引到索引集中了
execute ctx_ddl.add_index('reviewers','reviewer');

--常用语句

--创建索引集
    ctx_ddl.create_index_set('CIRCLE_INDEX_SET');
    ctx_ddl.add_index('CIRCLE_INDEX_SET','CREATETIME');
   
    --创建停用词列表
    ctx_ddl.create_stoplist('TAG_STOPLIST', 'BASIC_STOPLIST');
    --添加停用词
    ctx_ddl.add_stopword('TAG_STOPLIST','游戏');
    --删除停用词
    ctx_ddl.remove_stopword('TAG_STOPLIST','游戏');
    --删除停用词列表
    ctx_ddl.drop_stoplist('TAG_STOPLIST');
  
   --查询ctx_stoplists和ctx_stopwords 视图
   SELECT * FROM ctx_stoplists;
   SELECT * FROM ctx_stopwords;
   --查看系统默认参数项
   SELECT * FROM ctx_parameters;
   --查看索引集视图
   SELECT * FROM ctx_index_sets
    --创建全文索引
    CREATE INDEX CTXCAT_CIRCLE_TAG ON CIRCLE(TAG) INDEXTYPE IS CTXSYS.CTXCAT;
    --带停用词创建索引
    create index CTXCAT_CIRCLE_TAG on CIRCLE(TAG) indextype is CTXSYS.CTXCAT
    parameters ('stoplist TAG_STOPLIST');
    --带索引集创建索引
    CREATE INDEX CTXCAT_CIRCLE_TAG ON CIRCLE(TAG) INDEXTYPE IS CTXSYS.CTXCAT
    PARAMETERS ('index set CIRCLE_INDEX_SET');
   
    --删除索引
    DROP INDEX CTXCAT_CIRCLE_TAG;
   --重建索引
   ALTER INDEX CTXCAT_CIRCLE_TAG REBUILD
      PARAMETERS ('REPLACE STOPLIST TAG_STOPLIST');
   
   select * from (select  row_.*, rownum rownum_ from(
        SELECT * FROM CIRCLE c
        WHERE CATSEARCH(TAG,'游戏|漫画|旅游','order by createtime DESC')>0
   ) row_  where rownum <= 10) where rownum_ >= 0

--CTXCAT索引是CONTEXT索引的简化版

CTXCAT索引是CONTEXT索引的简化版,CTXCAT索引支持的PREFERENCE包括:LEXER、STOPLIST、WORDLIST和STORAGE参数。不支持其他的参数如:DATASTORE、FILTER、SECTION GROUP。虽然支持LEXER但不支持THEME查询,而且不支持FORMAT、CHARSET和LANGUAGE列,另外不支持表和索引分区。

CTXCAT索引仅仅包含了CONTEXT索引的部分内容,但是CTXCAT索引有其自身的优点。其中最突出的优点就是支持DML同步。CONTEXT索引由于结构过于复杂,且索引的数据量一般较大,因此CONTEXT索引并不是自动同步的。而CTXCAT索引是自动同步的,当发生了DML修改时,Oracle会自动同步CTXCAT索引,降低了索引的维护成本。

CTXCAT索引的另外一个优点就是这里要介绍的INDEX SET属性,这也是CTXCAT索引特有的属性。简单的说,CTXCAT可以建立一个索引集。可以把一些经常与CTXCAT查询组合使用的查询列的索引添加到索引集中。比如,如果在查询文章内容的同时,经常需要查询文章的作者、标题或创建时间等信息,则可以将这些信息列的索引添加到索引集中,Oracle可以将这些查询封装到CATSEARCH操作中,从而提高全文索引的效率。

下面看一个简单的例子:

SQL> CREATE TABLE T (ID NUMBER, TITLE VARCHAR2(256), CREATED DATE, DOCS VARCHAR2(4000));

表已创建。

SQL> INSERT INTO T VALUES (1, 'ORACLE TEXT REFERENCE', TO_DATE('200203', 'YYYYMM'),
2 'This manual provides reference information for Oracle Text. Use it as a reference for
3 creating Oracle Text indexes, for issuing Oracle Text queries, for presenting
4 documents, and for using the Oracle Text PL/SQL packages.');

已创建 1 行。

SQL> INSERT INTO T VALUES (2, 'ORACLE TEXT APPLICATION DEVELOPER''S GUIDE',
2 TO_DATE('200203', 'YYYYMM'),
3 'This guide explains how to build query applications with Oracle Text. This preface
4 contains these topics:');

已创建 1 行。

SQL> INSERT INTO T VALUES (3, 'ORACLE SQL REFERENCE', TO_DATE('200210', 'YYYYMM'),
2 'This reference contains a complete description of the Structured Query Language
3 (SQL) used to manage information in an Oracle database. Oracle SQL is a superset
4 of the American National Standards Institute (ANSI) and the International
5 Standards Organization (ISO) SQL99 standard.');

已创建 1 行。

SQL> COMMIT;

提交完成。

SQL> CREATE INDEX IND_T_DOCS ON T (DOCS) INDEXTYPE IS CTXSYS.CTXCAT;

索引已创建。

SQL> SET AUTOT ON EXP
SQL> SELECT ID FROM T WHERE CATSEARCH(DOCS, 'SQL', NULL) > 0;

ID
----------
1
3

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=8 Card=8 Bytes=16176)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T' (Cost=8 Card=8 Bytes=16176)
2 1 DOMAIN INDEX OF 'IND_T_DOCS'

SQL> SELECT ID FROM T WHERE CATSEARCH(DOCS, 'SQL', NULL) > 0
2 AND CREATED = TO_DATE('200203', 'YYYYMM');

ID
----------
1

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=8 Card=1 Bytes=2031)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T' (Cost=8 Card=1 Bytes=2031)
2 1 DOMAIN INDEX OF 'IND_T_DOCS'

SQL> CREATE INDEX IND_T_CREATED ON T (CREATED);

索引已创建。

SQL> SELECT ID FROM T WHERE CATSEARCH(DOCS, 'SQL', NULL) > 0
2 AND CREATED = TO_DATE('200203', 'YYYYMM');

ID
----------
1

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=11 Card=1 Bytes=2031)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T' (Cost=11 Card=1 Bytes=2031)
2 1 BITMAP CONVERSION (TO ROWIDS)
3 2 BITMAP AND
4 3 BITMAP CONVERSION (FROM ROWIDS)
5 4 INDEX (RANGE SCAN) OF 'IND_T_CREATED' (NON-UNIQUE) (Cost=1 Card=1)
6 3 BITMAP CONVERSION (FROM ROWIDS)
7 6 SORT (ORDER BY)
8 7 DOMAIN INDEX OF 'IND_T_DOCS'

SQL> DROP INDEX IND_T_DOCS;

索引已丢弃。

SQL> DROP INDEX IND_T_CREATED;

索引已丢弃。

上面的查询不仅包括了对DOCS列的全文索引查询还包括了对CREATED列的查询。Oracle采用了先将BTREE索引转化为BITMAP索引,在进行BITMAP索引的AND的方法进行了处理。而如果采用了INDEX SET的方法,则不需要如此复杂的转化:

SQL> CONN CTXSYS/CTXSYS@YANGTK
已连接。
SQL> BEGIN
2 CTX_DDL.CREATE_INDEX_SET('TEST_INDEXSET');
3 CTX_DDL.ADD_INDEX('TEST_INDEXSET', 'CREATED');
4 END;
5 /

PL/SQL 过程已成功完成。

SQL> CONN YANGTK/YANGTK@YANGTK
已连接。
SQL> CREATE INDEX IND_T_DOCS ON T (DOCS) INDEXTYPE IS CTXSYS.CTXCAT
2 PARAMETERS ('INDEX SET CTXSYS.TEST_INDEXSET');

索引已创建。

SQL> SET AUTOT ON EXP
SQL> SELECT ID FROM T WHERE CATSEARCH(DOCS, 'SQL', 'CREATED = TO_DATE(''200203'', ''YYYYMM'')') > 0;

ID
----------
1

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=8 Card=8 Bytes=16176)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T' (Cost=8 Card=8 Bytes=16176)
2 1 DOMAIN INDEX OF 'IND_T_DOCS'

处理支持结构性查询条件外,使用INDEX SET索引集还可以支持索引列的排序操作:

SQL> SET AUTOT OFF
SQL> SELECT ID FROM T WHERE CATSEARCH(DOCS, 'SQL', NULL) > 0;

ID
----------
1
3

SQL> SELECT ID FROM T WHERE CATSEARCH(DOCS, 'SQL', 'ORDER BY CREATED DESC') > 0;

ID
----------
3
1

这种将索引添加到索引集的操作也有一定的限制,比如结构性查询的操作只能包含大于、等于、小于、IN、BETWEEN AND操作。另外,加入到索引集中索引列的大小也有限制,对于VARCHAR2和CHAR类型,大小不能超过30字符,否则会报错:

SQL> SELECT ID FROM T WHERE CATSEARCH(DOCS, 'SQL', 'CREATED != TO_DATE(''200203'', ''YYYYMM'')') > 0;
SELECT ID FROM T WHERE CATSEARCH(DOCS, 'SQL', 'CREATED != TO_DATE(''200203'', ''YYYYMM'')') > 0
*
ERROR 位于第 1 行:
ORA-29902: 执行 ODCIIndexStart() 例行程序中出错
ORA-20000: Oracle Text error:
DRG-10844: 索引无法有效执行此结构化谓词
DRG-10845: 列 CREATED ! 未编制索引

SQL> DROP INDEX IND_T_DOCS;

索引已丢弃。

SQL> CONN CTXSYS/CTXSYS@YANGTK
已连接。
SQL> BEGIN
2 CTX_DDL.ADD_INDEX('TEST_INDEXSET', 'TITLE');
3 END;
4 /

PL/SQL 过程已成功完成。

SQL> CONN YANGTK/YANGTK@YANGTK
已连接。
SQL> CREATE INDEX IND_T_DOCS ON T (DOCS) INDEXTYPE IS CTXSYS.CTXCAT
2 PARAMETERS ('INDEX SET CTXSYS.TEST_INDEXSET');
CREATE INDEX IND_T_DOCS ON T (DOCS) INDEXTYPE IS CTXSYS.CTXCAT
*
ERROR 位于第 1 行:
ORA-29855: 执行 ODCIINDEXCREATE 例行程序时出错
ORA-20000: Oracle Text 错误:
DRG-12306: 列 TITLE 对于索引集列太长
ORA-06512: 在"CTXSYS.DRUE", line 157
ORA-06512: 在"CTXSYS.CATINDEXMETHODS", line 100

抱歉!评论已关闭.