PostgreSQL 의 중국어 병 음 정렬 사례

얼마 전 개발 자 는 postgresql 에서 한 필드 에 따라 중국어 병 음 순 서 를 매기 고 싶 지만 이해 할 수 없다 고 문의 했다.
환경:
OS:CentOS 6.3
DB:PostgreSQL 9.2.4
TABLE: tbl_kenyon
필드:

postgres=# \d tbl_kenyon 
  Table "public.tbl_kenyon"
 Column | Type |  Modifiers  
--------+------+---------------
 vname | text |
--정렬 후 결 과 를 사용 하 는 것 이 바람 직 하지 않다

postgres=# select vname from tbl_kenyon order by vname;
 vname 
-------
   
   
   
   
(4 rows)
설명:
post gresql 의 정렬 은 데이터 뱅 크 의 인 코딩 영향 을 받 는 것 외 에 도 초기 화 된 매개 변 수 는 locale 도 영향 을 줄 수 있 습 니 다(initdb).보통 제 선택 은 C 입 니 다.이것 은 post gres 데이터 베 이 스 를 strcmp()함수 가 아 닌 strcoll 함수 로 문자열 을 비교 할 수 있 습 니 다.
이 매개 변 수 는 데이터베이스 에서 볼 수 있 습 니 다.예 를 들 어

postgres=# \l
                List of databases
   Name    | Owner  | Encoding | Collate | Ctype |  Access privileges  
-----------------+----------+----------+---------+-------+-----------------------
 dkenyon     | u_kenyon | UTF8   | C    | C   | 
 postgres    | postgres | UTF8   | C    | C   | 
 template0    | postgres | UTF8   | C    | C   | =c/postgres     +
         |     |     |     |    | postgres=CTc/postgres
 template1    | postgres | UTF8   | C    | C   | =c/postgres     +
         |     |     |     |    | postgres=CTc/postgres
(6 rows)
--시스템 테이블 에서 중국어 간 체 지원

postgres=# select collname,collcollate,collctype,b.nspname,c.rolname as collowner 
postgres-# from pg_collation a,pg_namespace b,pg_authid c 
postgres-# where a.collnamespace = b.oid and a.collowner = c.oid and lower(collname) like '%zh_cn%';
  collname  | collcollate | collctype  | nspname  | collowner 
--------------+--------------+--------------+------------+-----------
 zh_CN    | zh_CN    | zh_CN    | pg_catalog | postgres
 zh_CN    | zh_CN.utf8  | zh_CN.utf8  | pg_catalog | postgres
 zh_CN.gb2312 | zh_CN.gb2312 | zh_CN.gb2312 | pg_catalog | postgres
 zh_CN.utf8  | zh_CN.utf8  | zh_CN.utf8  | pg_catalog | postgres
(4 rows)
초기 화 할 때 선택 한 locale 은 C 이기 때문에 데이터베이스 의 기본 정렬 도 C 입 니 다.필드 내용 을 중국어 병 음 으로 정렬 하려 면 UTF 8 형식 으로 저 장 된 내용 을 GBK 방식 으로 변환 해 야 합 니 다.
해결 방법:
1.필드 전환 방식,convert 추가접두사 함수

postgres=# select vname from tbl_kenyon order by convert_to(vname,'GBK');
 vname 
 
-------
   
   
   
   
(4 rows)
--convert_to 함수 입력 매개 변 수 는 text 형식 이 고 출력 인 코딩 은 bytea 형식 이 며 문 자 를 대상 인 코딩 으로 변환 하 는 함수 입 니 다.예 를 들 어

postgres=# select convert_to('  ','UTF8'),('  ','GBK');
  convert_to  |  row   
----------------+------------
 \xe6b599e6b19f | (  ,GBK)
(1 row)
2.열 지정 zhcn 방식 저장

postgres=# alter table tbl_kenyon add cname text collate "zh_CN";
ALTER TABLE
postgres=# \d tbl_kenyon 
  Table "public.tbl_kenyon"
 Column | Type |  Modifiers  
--------+------+---------------
 vname | text | 
 cname | text | collate zh_CN
postgres=# select * from tbl_kenyon;
 vname | cname 
-------+-------
    |   
    |   
    |   
    |   
(4 rows)
postgres=# select * from tbl_kenyon order by vname;
 vname | cname 
-------+-------
    |   
    |   
    |   
    |   
(4 rows)
postgres=# select * from tbl_kenyon order by cname;
 vname | cname 
-------+-------
    |   
    |   
    |   
    |   
(4 rows)
3.조회 시 collate 지정

postgres=# select * from tbl_kenyon order by vname collate "C";
 vname | cname 
-------+-------
    |   
    |   
    |   
    |   
(4 rows)
postgres=# select * from tbl_kenyon order by vname collate "zh_CN";
 vname | cname 
-------+-------
    |   
    |   
    |   
    |   
(4 rows)
기타 질문:
1.방법 1 을 사용 한 convertto 함수 변환 시간 후,개발 은 나 에 게 이상 이 있다 고 말 했 습 니 다.character with byte sequence 0xc 2 0xae in encoding"UTF 8"has no equivalent in encoding"GBK"

Error querying database. Cause: org.postgresql.util.PSQLException: ERROR: character with byte sequence 0xc2 0xae in
 encoding "UTF8" has no equivalent in encoding "GBK"
조사 한 결과 데이터베이스 에 비교적 이상 한 문자 가 저장 되 어 있 는 것 을 발견 했다.예 를 들 어 Mircle®city,niwhite®town。나중에 이 시 계 를 재건 하고 방법 2 로 해결 하기 때문에 convertto 함수 가 이상 한 문자 변환 을 사용 할 때 주의해 야 합 니 다.
2.다 음 자 에 대해 일정한 다른 의미 가 생 길 수 있다.예 를 들 어 충 칭 은 Z 에 따라 순 위 를 매 긴 다.
상술 한 방법 은 대부분의 한자 의 병 음 순 서 를 만족 시 킬 수 있 지만 여전히 약간 부족 하 다.비교적 이상 적 인 해결 방법 은 이러한 기초 데 이 터 를 입력 할 때 병 음 규칙 을 지정 하거나 데이터 베이스 에 데 이 터 를 저장 하 는 병 음 사전 을 사용 하 는 것 이다.
기타:
zh 사용cn 저장 시 필드 크기 측정,추출 속도 테스트 하지 않 음

postgres=# insert into tbl_kenyon select repeat('  GDOOASASHOME  ',5000), repeat('  GDOOASASHOME  ',5000) ;
INSERT 0 1
postgres=# insert into tbl_kenyon select repeat('  GDOOASASHOME  ',50000), repeat('  GDOOASASHOME  ',50000) ;
INSERT 0 1
postgres=# insert into tbl_kenyon select repeat('  GDOOASASHOME  ',100000), repeat('  GDOOASASHOME  ',100000) ;
INSERT 0 1
postgres=# select pg_column_size(cname),pg_column_size(vname) from tbl_kenyon ;
 pg_column_size | pg_column_size 
----------------+----------------
      1410 |      1406
     13769 |     13769
     27506 |     27506
(3 rows)
메모리 차이 가 크 지 않 습 니 다.
보충 하 다

#        ,      ?
select * from store order by storename collate 'zh_CN';
이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.만약 잘못 이 있 거나 완전히 고려 하지 않 은 부분 이 있다 면 아낌없이 가르침 을 주시 기 바 랍 니 다.

좋은 웹페이지 즐겨찾기