我申请这个blog是为了督促自己,把自己平时的一些想法和思考结果保留下来。 本博客所有内容均为原创,如有转载请注明作者和出处

获取汉字拼音首字母

上一篇 / 下一篇  2008-05-25 21:39:39 / 个人分类:ORACLE

Oracle中获取汉字的拼音其实并不算复杂,这篇文章给出一个获取汉字拼音首字母的例子,并简单说明思路。

 

 

最近有个需求,要根据中文来获取汉语拼音的首字母。记得很早以前版主chensqjlandzpa就给出过解决方法。不过这么简单的需求没有必要再去费劲找了,自己写一个就可以了。

介绍一下处理的思路,最简单的思路莫过于构造一个汉字库,手工为所有的汉字添加拼音,但是这种方法需要大量的人工录入工作,如果可以找到现成的字库倒是可以考虑。

那么能否利用Oracle提供的现有功能来解决。首先想到的是Oracle提供了SOUNDEX函数:

SQL> SELECT SOUNDEX('WORD') FROM DUAL;

SOUN
.o:EI9X z!t"d2Xw(cT0----ITPUB个人空间-k Z'^p~/R K N
W630

SQL> SELECT SOUNDEX('') FROM DUAL;

SITPUB个人空间3^ V(c2B&W*VH~3e3cn
-

可惜的是,这个函数只对英文有效,对中文无效。看来只能使用其他的方法。

Oracle对各个国家不同的语言进行了本地化的开发,这其中就包括排序方式。查询了一下Oracle对于中文的排序支持,果然发现了对简体中文拼音的支持。

OracleSCHINESE_PINYIN_M排序方式可以支持中文的拼音排序,下面简单看一下使用这个中文拼音排序的例子:

SQL> WITH A AS
^*x$o#JQ#u0  2  (SELECT '
获取汉字拼音首字母' W FROM DUAL)
k` Q} wt3j0  3  SELECT SUBSTR(W, ROWNUM, 1) FROM A
&w-AKxO]V0  4  CONNECT BY ROWNUM <= (SELECT LENGTH(W) FROM A);

SUITPUB个人空间j}esc R1pH
--
N!g"R(CD#p'ME _U0

,x1L.tIz8p[2t0
ITPUB个人空间dUT"g*Wh
ITPUB个人空间 {&U`1c,n5zJ{$^
ITPUB个人空间 z9i:N}o5w b&Y
ITPUB个人空间gD3E%FN:?&aR#D

'X+UsO {X rjZ0
ITPUB个人空间|+^.jUz Rw:c
ITPUB个人空间S EU1b `

已选择9行。

下面加上NLSSORT排序,并指定排序方法为SCHINESE_PINYIN_M

SQL> WITH A AS
,|!pC:w'??K#R M0  2  (SELECT '
获取汉字拼音首字母' W FROM DUAL)ITPUB个人空间 en\"~T1PU$S:H5J
  3  SELECT SUBSTR(W, ROWNUM, 1) FROM A ITPUB个人空间`0e Qb*v.t{X!H$K
  4  CONNECT BY ROWNUM <= (SELECT LENGTH(W) FROM A)
E]L.H#B1x8q1_ }0  5  ORDER BY NLSSORT(SUBSTR(W, ROWNUM, 1), 'NLS_SORT=SCHINESE_PINYIN_M');

SU
V!A&qws6k5~ _ sY#GgC0--
8rz H_&D0

{g(wvJ(ACs0
ITPUB个人空间*f;eIu8U~\&yb

%i;i`-@ vZ9T0
ITPUB个人空间#`3Fm#d P;Y!O
ITPUB个人空间0e3o-i VDD,A `
ITPUB个人空间&Jq:m+U`;W`UGV D

R+[7W9ZJ`0

:}qCy;M6T0

已选择9行。

利用Oracle的现成的排序方法,编写获取拼音首字母的函数就十分容易了,只需要找到每个首字母对应开头汉字和结尾汉字,根据这些边界汉字进行比较,就可以找到当前汉字的首字母信息。

SQL> WITH A AS
\1m+v.yJ+UZ9ui P0  2  (
$F {"DO'o.F;O K0  3   SELECT ROWNUM RN, CHR(ROWNUM) C FROM DUAL CONNECT BY LEVEL <= 65535ITPUB个人空间s6F(W2H @
  4  )
4i8l:w e8r&nZ0  5  SELECT * FROM A WHERE LENGTHB(C) = 2
9pQSn-@m%g)c0  6  AND RN > 32768
.H|)eASE3}$~ M(~0  7  AND NLSSORT(C, 'NLS_SORT=SCHINESE_PINYIN_M') > NLSSORT('
', 'NLS_SORT=SCHINESE_PINYIN_M')ITPUB个人空间!E$_&`C6C hK E
  8  AND NLSSORT(C, 'NLS_SORT=SCHINESE_PINYIN_M') < NLSSORT('
', 'NLS_SORT=SCHINESE_PINYIN_M')ITPUB个人空间0\X|2YW2w$bQ!vt:W
  9  ORDER BY NLSSORT(C, 'NLS_SORT=SCHINESE_PINYIN_M');

        RN CITPUB个人空间Q'nh }&e/~
---------- --ITPUB个人空间:zUT#M7WQ*Jk
     54931
ITPUB个人空间\:H%o^]4w
     63179
ITPUB个人空间l*e"X*D;n [A!M
     62088

"R4L+K.o8e e \&Y8~0     45259
ITPUB个人空间+UUeWM"Z3^J
     33172

利用类似这样的方法,就可以分别找到每个首字母对应的字头和字尾。下面构建一个函数就十分容易了:

SQL> CREATE OR REPLACE FUNCTION F_PINYIN(P_NAME IN VARCHAR2) RETURN VARCHAR2 AS
7LbTq` a8k^R0  2   V_COMPARE VARCHAR2(100);ITPUB个人空间`-Z|i C \ O5g
  3   V_RETURN VARCHAR2(4000);ITPUB个人空间9fu+^Qb
  4  
G"gS6G4UaH;i'{ D0  5   FUNCTION F_NLSSORT(P_WORD IN VARCHAR2) RETURN VARCHAR2 ASITPUB个人空间 MxDn0w{'VY
  6   BEGIN
;W(Cn&~]0  7    RETURN NLSSORT(P_WORD, 'NLS_SORT=SCHINESE_PINYIN_M');ITPUB个人空间f r.M,_#H4`)a
  8   END;
|t UYrM-P:T$p0  9  BEGIN
Fa5n$Vd Tz0 10  
Sj ~c0J.u q;t|0^/L0 11   FOR I IN 1..NVL(LENGTH(P_NAME), 0) LOOP
2b3g:w{,AB"wBP0 12    V_COMPARE := F_NLSSORT(SUBSTR(P_NAME, I, 1));
e%g'Y%DK&@0 13    IF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('') THEN
'Y;F6vkv&D_|.XV0 14     V_RETURN := V_RETURN || 'A';
'p@8[(D(xe*D0 15    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('簿
') THENITPUB个人空间'k%s)u$E)]"f1V$iz
 16     V_RETURN := V_RETURN || 'B';ITPUB个人空间&I m-q?~!K;c
 17    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THEN
(a0uWrz6J!]0 18     V_RETURN := V_RETURN || 'C';ITPUB个人空间7k3Z2y8X~)es*W
 19    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THEN
_S HrOo(kX/f0 20     V_RETURN := V_RETURN || 'D';
3LSdkGr.X0 21    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THEN
T;? W(i(m+U2uu6R0 22     V_RETURN := V_RETURN || 'E';ITPUB个人空间!@:P0sG#PY/g^l
 23    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THENITPUB个人空间9fy j4h9q4fWX
 24     V_RETURN := V_RETURN || 'F';
Nw}OLj7js0 25    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THEN
.U9DK*O B.[E/b0 26     V_RETURN := V_RETURN || 'G';ITPUB个人空间 |T~#MAO]
 27    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THEN
tG/~K F Kl N0 28     V_RETURN := V_RETURN || 'H';ITPUB个人空间7b%O @&kf!g
 29    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THENITPUB个人空间mkX1| g9K }
 30     V_RETURN := V_RETURN || 'J';
GSx$D7D2{l vp0 31    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THEN
MFk-f/M0 32     V_RETURN := V_RETURN || 'K';
`;LGep$LdS\'c0 33    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THENITPUB个人空间!T-^ ?ND4s2|9zs8l2h
 34     V_RETURN := V_RETURN || 'L';
7Q"Sp4Q-R^/[0 35    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THEN
t8XsSY-B9~0 36     V_RETURN := V_RETURN || 'M';ITPUB个人空间7|)y{Yf0|+k
 37    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THEN
R4Na'wLW _*J8O0 38     V_RETURN := V_RETURN || 'N';
z`,|3_c~0 39    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THEN
}"f~i;I%s+^t J$F}0 40     V_RETURN := V_RETURN || 'O';ITPUB个人空间kA)yi:W5^ c1w#F*R
 41    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THEN
,Vj#oD%U0 42     V_RETURN := V_RETURN || 'P';ITPUB个人空间j s5d6CT0{Ll(RwY
 43    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THEN
P,[ D;]8l1tr8l T+\7A0 44     V_RETURN := V_RETURN || 'Q';
*_2`?+Vi0 45    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THEN
2z;Nh^ f _'z's(h@0 46     V_RETURN := V_RETURN || 'R';
QG P u5lv,__zW0 47    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THENITPUB个人空间JFF Uz%e3N+xd$y
 48     V_RETURN := V_RETURN || 'S';
B;FSP&h8v~2r0 49    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THEN
-?2CDX0lU3R3u/m;M0 50     V_RETURN := V_RETURN || 'T';
(A$b q m8h$`hb0 51    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THEN
i.[C$J2B ~@ b0 52     V_RETURN := V_RETURN || 'W';
!zK,@"[GO5[-f6q0 53    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THEN
pU3Jb2a0 54     V_RETURN := V_RETURN || 'X';ITPUB个人空间q!bL'I+QBa
 55    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THENITPUB个人空间(yi{,GN
 56     V_RETURN := V_RETURN || 'Y';ITPUB个人空间9fr S;G4WR(_)UV?]
 57    ELSIF V_COMPARE >= F_NLSSORT('
') AND V_COMPARE <= F_NLSSORT('
') THEN
tP2D?$J+~qE?0 58     V_RETURN := V_RETURN || 'Z';
Rj_SGV0 59    END IF;
"ry |(g2L8DU0 60   END LOOP;ITPUB个人空间6^ g([+SO g
 61   RETURN V_RETURN;
7|NPcz8|ia0h0 62  END;ITPUB个人空间!hA_ Z/m6q)vF9}8c1n]
 63  /

函数已创建。

SQL> SELECT F_PINYIN('函数已创建。') FROM DUAL;

F_PINYIN('函数已创建。')ITPUB个人空间1m&p/{.`~X%Z
-------------------------------------------------------------------ITPUB个人空间GWy+Puq J@V
HSYCJ

用类似的方法,获取一个汉字的整个拼音也是可行的,只不过确定字头字尾的工作会更加的繁琐。

需要说明的是,这种方法很难处理多音字,一般来说,多音字只能根据Oracle的排序中采用的拼音来返回结果。另外,Oracle实现的拼音排序难免存在错误,如果发现了错误,可以通过对个别字单独处理的方式来改写上面的代码。

这个函数在ZHS16GBK字符集下编写,不保证在其他字符集下也能正常工作,不过编写函数的思路应该是一样的。

 


TAG:

引用 删除 Guest   /   2008-10-13 17:33:49
5
 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

Open Toolbar