今天在ITPUB上看到这样一个需求,给出一个中文语句,如何对其实现切词。
如果Oracle全文索引的切词可以满足需求的话,那么可以借用Oracle的功能来实现这个功能。
对前两天给出的实现进行了一些修改,考虑了并发性,并降低执行成本。
利用Oracle的全文索引实现切词功能:http://yangtingkun.itpub.net/post/468/453753
这次的修改主要是考虑并发性,因此必须替换掉CREATE/DROP等DDL语句。采用DML的方式,每次读取当前插入记录对应的切词记录。同时利用CTXCAT类型索引来替换CONTEXT索引类型,这样可以实现索引更新同步,同时为了方便查询到指定记录的切词信息。
首先进行准备工作,由于要避免DDL,因此建表、索引的操作必须提前完成:
SQL> BEGIN
L]oUV"qU\E0 2 CTX_DDL.CREATE_PREFERENCE('MY_CHINESE_LEXER', 'CHINESE_LEXER');ITPUB个人空间
Bq7KF,Hv8R
3 CTX_DDL.CREATE_INDEX_SET('MY_INDEX_SET');
JYdBD3l5q0 4 CTX_DDL.ADD_INDEX('MY_INDEX_SET', 'ID');ITPUB个人空间 X+f+rO0]8Ffc
5 END;
)lB)N|7D6D4J0 6 /
PL/SQL过程已成功完成。
SQL> CREATE TABLE T_TEMP_TABLE (ID NUMBER, DOC VARCHAR2(1000));
表已创建。
SQL> CREATE INDEX IND_T_TEMP_TABLE_DOC ON T_TEMP_TABLE(DOC) INDEXTYPE IS CTXSYS.CTXCATITPUB个人空间:V0n8i,z5T
2 PARAMETERS ('LEXER MY_CHINESE_LEXER INDEX SET MY_INDEX_SET');
索引已创建。
SQL> CREATE SEQUENCE SEQ_TEMP_TABLE;
序列已创建。
下面创建存储过程:
SQL> CREATE OR REPLACE FUNCTION F_SPLIT_CHINESE(P_INPUT IN VARCHAR2) RETURN VARCHAR2 AS
S`#@"T+FC3k&^0 2 PRAGMA AUTONOMOUS_TRANSACTION;
}z,CH|u N"o0 3 V_ID NUMBER;ITPUB个人空间G's6O!AvA a
4 V_RETURN VARCHAR2(32767);ITPUB个人空间}2B S{4}
5 BEGIN
gL5V5k'a0 6 INSERT INTO T_TEMP_TABLE (ID, DOC) VALUES (SEQ_TEMP_TABLE.NEXTVAL, P_INPUT) RETURN ID INTO V_ID;
~.?m2e+O0 7 SELECT MAX(LTRIM(SYS_CONNECT_BY_PATH(DR$TOKEN, ','), ','))
2cL%@(T0@`!p6I0 8 INTO V_RETURNITPUB个人空间^ E}.\(h5?m7~#K5u
9 FROMITPUB个人空间-}An'Kc,pR B
10 (ITPUB个人空间*A+o(V%b*hu"f
11 SELECT DR$TOKEN, ROW_NUMBER() OVER(ORDER BY DR$TOKEN) RNITPUB个人空间!Y8],|Fb9u&m/_1n
12 FROM DR$IND_T_TEMP_TABLE_DOC$I
~~'G0n"x_0 13 WHERE ID = V_ID
|y};^/^&d\'Y0 14 )ITPUB个人空间
n/{M+LC7l\_%A@ P
15 START WITH RN = 1
b&C9_ ~4|.u0 16 CONNECT BY PRIOR RN + 1 = RN;ITPUB个人空间$gCCN
^ j4`
n
17 ROLLBACK;
d'b8f%h'zR0 18 RETURN V_RETURN;ITPUB个人空间(Q9I%k]o
19 END;
C^z_ dE0 20 /
函数已创建。
SQL> SELECT F_SPLIT_CHINESE('测试一下中文环境') FROM DUAL;
F_SPLIT_CHINESE('测试一下中文环境')ITPUB个人空间
KNI/`F}
---------------------------------------------------ITPUB个人空间T:Cf:y&q[
测试,环境,一下,中文
通过改进方法,使得系统增加了并发处理能力。