Chinaunix首页 | 论坛 | 博客
  • 博客访问: 103570702
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类: Oracle

2008-03-31 13:02:40

来源:赛迪网    作者:林梦

问题:给出一个中文语句,怎样才能对其实现切词功能功能?

解答:假如Oracle全文索引的切词可以满足需求的话,那么可以借用Oracle的功能来实现切词功能。

Oracle的全文索引本身具备中文分析、切词功能,否则就无法有效的对中文进行搜索,如果这个切词结果可以满足要求的话,那么可以自己封装一个函数,来借用Oracle的功能。

由于建立全文索引函数后,Oracle会将切词结果放到DR$index_name$I表中,因此获取这个表中的记录就可以得到最终的切词结果。

建立自定义函数的时候注意,由于这个操作包括很多DDL操作,因此如果希望这个函数可以在SQL中被调用,就必须使用自主事务。

为了方便的选择CHINESE_LEXER还是CHINESE_VGRAM_LEXER,将MY_CHINESE_LEXER的创建放到了函数之外,这样方便对切词规则进行修改。这个过程也是唯一需要在建立自定义函数之前做的步骤。

以下是实现这个功能的建立的例子:

SQL> EXEC CTX_DDL.CREATE_PREFERENCE('MY_CHINESE_LEXER', 'CHINESE_VGRAM_LEXER')

PL/SQL 过程已成功完成。

SQL> CREATE OR REPLACE FUNCTION F_SPLIT_CHINESE
(P_INPUT IN VARCHAR2) RETURN VARCHAR2 AS
2 PRAGMA AUTONOMOUS_TRANSACTION; V_RETURN VARCHAR2(32767);
3 BEGIN
4 BEGIN
5 EXECUTE IMMEDIATE 'DROP TABLE T_TEMP_TABLE PURGE';
6 EXCEPTION
7 WHEN OTHERS THEN
8 NULL;
9 END;
10 
11 EXECUTE IMMEDIATE 'CREATE TABLE T_TEMP_TABLE (STR VARCHAR2(4000))';
12 EXECUTE IMMEDIATE 'INSERT INTO T_TEMP_TABLE VALUES (:STR)' USING P_INPUT;
13 EXECUTE IMMEDIATE 'CREATE INDEX IND_T_TEMP_TABLE_STR 
ON T_TEMP_TABLE(STR) INDEXTYPE IS CTXSYS.CONTEXT
14 PARAMETERS(''LEXER MY_CHINESE_LEXER'')';
15 EXECUTE IMMEDIATE 'SELECT MAX(LTRIM
(SYS_CONNECT_BY_PATH(TOKEN_TEXT, '',''), '',''))
16 FROM 
17 (
18 SELECT TOKEN_TEXT, ROW_NUMBER() OVER(ORDER BY TOKEN_TEXT) RN
19 FROM DR$IND_T_TEMP_TABLE_STR$I
20 ) 
21 START WITH RN = 1
22 CONNECT BY PRIOR RN + 1 = RN' INTO V_RETURN;
23 EXECUTE IMMEDIATE 'DROP TABLE T_TEMP_TABLE PURGE';
24 RETURN V_RETURN;
25 END;
26 /

函数已创建。

SQL> SELECT F_SPLIT_CHINESE('测试一下中文切词') FROM DUAL;

F_SPLIT_CHINESE('测试一下中文切词')
---------------------测试,词,切词,试一,文切,下中,一下,中文

SQL> EXEC CTX_DDL.DROP_PREFERENCE('MY_CHINESE_LEXER')

PL/SQL 过程已成功完成。

SQL> EXEC CTX_DDL.CREATE_PREFERENCE('MY_CHINESE_LEXER', 'CHINESE_LEXER')

PL/SQL 过程已成功完成。

SQL> SELECT F_SPLIT_CHINESE('测试一下中文切词') FROM DUAL;

F_SPLIT_CHINESE('测试一下中文切词')
----------------------------------测试,词,切词,一下,中文

通过修改不同的LEXER语法,可以明显的看出CHINESE_VGRAM_LEXER和CHINESE_LEXER在中文分词上的区别。关于二者区别的一些描述可以参考:http://yangtingkun.itpub.net/post/468/187632

需要注意的是,这个函数声明了自主事务,虽然可以在SQL中调用,但是并不意味着这个函数不修改数据库中的内容。

这个函数在调用的过程中会执行建表、建立索引、删除表等一系列操作。因此调用这个函数的SELECT语句,不但会引起数据库数据的变化,而且会导致DDL的发生,导致很多的递归调用、逻辑读和REDO的产生。这是在使用这个函数之前需要理解的。

注释:此函数在Oracle 10g的环境中完成,如果大家需要在Oracle 9i版本中使用,必须将DROP语句中的PURGE语句去掉,否则会出现语法错误

阅读(524) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~