積ん読 2010/02/01

PostgreSQL の ソート順

CentOS や Redhat で PostgreSQL を入れた時に 日本語のソート順がおかしくなることがあります。

       item_nm
----------------------
 くり
 なし
 もも
 みかん
 りんご
 いちじく
 さくらんぼ

50 音順ではなく文字数の順番で 並んでしまうことがあります。

$ pg_controldata /var/lib/pgsql/data

Debian 系は /usr/lib/postgresql/x.y/bin/pg_controldata に あります。 (x.y は 8.1 などのバージョンです)

$ /usr/lib/postgresql/x.y/bin/pg_controldata \
    /var/lib/postgresql/x.y/main/

この結果で、LC_COLLATE や LC_CTYPE が 下のように出力される場合、 日本語のソートがおかしくなります。

LC_COLLATE:     en_US.UTF-8
LC_CTYPE:       en_US.UTF-8 

CentOS などでは、/etc/init.d/pgsql を実行したときに $PGDATA (/var/lib/pgsql/data) が存在しないと initdb を実行するのですが そのときのオプションに --no-local の指定がないので OS の環境がそのままセットされてしまうわけです。

ちなみに PostgreSQL CE の試験でも 日本語を使用する場合は --no-local を指定するのが良いとされていました。

こうなっている場合、initdb からやりなおす必要があります。 既存のデータはダンプを取っておけばリストアすることができます。

$PGDATA (/var/lib/pgsql/data) をリネームして 手動で "initdb --no-local" を実行することで pg_controldata の結果が次のようになります。

LC_COLLATE:     C
LC_CTYPE:       C

ソート順も正しくなります。

       item_nm
----------------------
 いちじく
 くり
 さくらんぼ
 なし
 みかん
 もも
 りんご

OS 全体を変えても問題ない場合は、 /etc/sysconfig/i18n を修正するという手もあるようです。

LANG="ja_JP.UTF-8" # (修正後)

この場合 --no-local を設定する必要がなくなるので 既存の $PGDATA を消して /etc/init.d/pgsql を実行するだけです。

いずれにせよ、既存のデータがある場合 initdb を実行する前に 退避させておかないといけないので 注意してください。

Google サイト内検索

Amazonアソシエイト