2014/11/26
CentOS と PostgreSQL のロケール
[CentOS][PostgreSQL]2014/09/21 に CentOS 6.5 へ PostgresQL をインストールし、同様に昨日 6.6 にインストールしましたが、振り返ると2回とも、最初の initdb 実行で付けたオプション --locale=ja_JP.UTF-8 は日本語を使える状態になかったので無意味でした。cat /etc/sysconfig/i18n で見ると ↓ en_US.UTF-8 が OS の言語になっていました。

↓ PostgreSQL のデフォルトのロケールも en_US.UTF-8。

列 encoding の数値を関数 pg_encoding_to_char に渡すと ↓ 文字コード名が返ります。上のデータベースは全て 6 なので UTF-8 です。

これまでロケールに左右されるような文字ソートや書式設定の経験がないので無頓着でしたが、この機会に Windows 7 上の PostgreSQL と文字ソート順が違う例を確認してみます。Windows では EnterpriseDB 社のインストーラをデフォルトで使い、下のように文字コード UTF-8、ロケール Japanese_Japan.932 になっています。

↓ ひらがな・カタカナを昇順に並べるクエリ。これを両方の PostgreSQL で実行します。
↓ CentOS(ロケール en_US.UTF-8)では「ひらがな全体 → カタカナ全体」の順。これはコード番号(ascii の戻り値)の昇順と同じです。

↓ Windows(ロケール Japanese_Japan.932)では、アイウエオ一つずつ「カタカナ → ひらがな」の順に並びます。

↓ 今度は、半角英大文字・同小文字・全角英大字を昇順に並べるクエリ。
↓ CentOS(ロケール en_US.UTF-8)では、全体が「全角英大 → 半角」の順で、後者の中がアルファベット一つずつ「小文字 → 大文字」の順。先ほどのひらがな・カタカナがコード番号の順と同じだったのに対し、今度は違いました。

↓ Windows(ロケール Japanese_Japan.932)では、アルファベット一つずつ「半角小 → 半角大 → 全角大」の順。

このように文字種を混在させてソートするとロケールによって結果がずいぶん違うと分かりました。引き続き Windows と CentOS 上で別々のロケールで PostgreSQL を使い、注意が必要な例があれば記事にします。下は、今回参考になったウェブページです。
■ Let's postgres : ロケール(国際化と地域化)
■ PostgreSQL 9.3.2文書 : initdb
■ PostgreSQL 9.3.2文書 : 文字セットサポート
■ PostgreSQLのソート順がおかしいためロケール再設定とinitdbやり直し
↓ PostgreSQL のデフォルトのロケールも en_US.UTF-8。
列 encoding の数値を関数 pg_encoding_to_char に渡すと ↓ 文字コード名が返ります。上のデータベースは全て 6 なので UTF-8 です。
これまでロケールに左右されるような文字ソートや書式設定の経験がないので無頓着でしたが、この機会に Windows 7 上の PostgreSQL と文字ソート順が違う例を確認してみます。Windows では EnterpriseDB 社のインストーラをデフォルトで使い、下のように文字コード UTF-8、ロケール Japanese_Japan.932 になっています。
↓ ひらがな・カタカナを昇順に並べるクエリ。これを両方の PostgreSQL で実行します。
WITH a AS (
SELECT * FROM generate_series(ascii('あ'), ascii('を')) ascii
UNION ALL SELECT * FROM generate_series(ascii('ア'), ascii('ヲ'))
), b AS (
SELECT chr(ascii) FROM a
)
SELECT array_agg(chr ORDER BY chr) FROM b ;
-- // コード番号順と等しいか確認する場合
-- // SELECT array_agg(chr ORDER BY chr) = array_agg(chr ORDER BY ascii(chr)) FROM b ;
SELECT * FROM generate_series(ascii('あ'), ascii('を')) ascii
UNION ALL SELECT * FROM generate_series(ascii('ア'), ascii('ヲ'))
), b AS (
SELECT chr(ascii) FROM a
)
SELECT array_agg(chr ORDER BY chr) FROM b ;
-- // コード番号順と等しいか確認する場合
-- // SELECT array_agg(chr ORDER BY chr) = array_agg(chr ORDER BY ascii(chr)) FROM b ;
↓ CentOS(ロケール en_US.UTF-8)では「ひらがな全体 → カタカナ全体」の順。これはコード番号(ascii の戻り値)の昇順と同じです。
↓ Windows(ロケール Japanese_Japan.932)では、アイウエオ一つずつ「カタカナ → ひらがな」の順に並びます。
↓ 今度は、半角英大文字・同小文字・全角英大字を昇順に並べるクエリ。
WITH a AS (
SELECT * FROM generate_series(ascii('A'), ascii('Z')) ascii
UNION ALL SELECT * FROM generate_series(ascii('A'), ascii('Z'))
UNION ALL SELECT * FROM generate_series(ascii('a'), ascii('z'))
), b AS (
SELECT chr(ascii) FROM a
)
SELECT array_agg(chr ORDER BY chr) FROM b ;
SELECT * FROM generate_series(ascii('A'), ascii('Z')) ascii
UNION ALL SELECT * FROM generate_series(ascii('A'), ascii('Z'))
UNION ALL SELECT * FROM generate_series(ascii('a'), ascii('z'))
), b AS (
SELECT chr(ascii) FROM a
)
SELECT array_agg(chr ORDER BY chr) FROM b ;
↓ CentOS(ロケール en_US.UTF-8)では、全体が「全角英大 → 半角」の順で、後者の中がアルファベット一つずつ「小文字 → 大文字」の順。先ほどのひらがな・カタカナがコード番号の順と同じだったのに対し、今度は違いました。
↓ Windows(ロケール Japanese_Japan.932)では、アルファベット一つずつ「半角小 → 半角大 → 全角大」の順。
このように文字種を混在させてソートするとロケールによって結果がずいぶん違うと分かりました。引き続き Windows と CentOS 上で別々のロケールで PostgreSQL を使い、注意が必要な例があれば記事にします。下は、今回参考になったウェブページです。
■ Let's postgres : ロケール(国際化と地域化)
■ PostgreSQL 9.3.2文書 : initdb
■ PostgreSQL 9.3.2文書 : 文字セットサポート
■ PostgreSQLのソート順がおかしいためロケール再設定とinitdbやり直し
タグと個別記事
・ PostgreSQL・ PostGIS
・ Python
・ R
・ Qt
2014/09/16 まで
・ Top・ PostgreSQL
・ PostGIS
・ R
・ データいろいろ
日本語ドキュメント
(外部リンク)
・ PostgreSQL(外部リンク)
・ PostGIS
公式ウェブサイト
・ PostgreSQL・ PostGIS
・ Python
・ R
・ Qt Project
・ CentOS