※当サイトの記事には、広告・プロモーションが含まれます。

PostgreSQLのデータベースの文字セットについて調べてみる

gigazine.net

IMEIは携帯電話を一意に識別することを目的とした15桁の番号です。1990年代に携帯電話が登場した際、非常に高価な携帯電話が盗難されて悪用されるケースを想定し、欧州で携帯電話の端末に「一意で管理可能なコード」の設定が義務付けられ、携帯電話メーカーや通信事業者の業界団体であるGSMアソシエーションがIMEIの仕様を開発しました。

スマホやタブレットに割り当てられている「IMEI」とは一体どんな番号なのか? - GIGAZINE

2000年以降、IMEIはGSMアソシエーションによって割り当てと管理が行われています。現在では、IMEIは盗難防止だけでなく、デバイスの追跡やサービスの提供など、さまざまな用途に使用されています。

スマホやタブレットに割り当てられている「IMEI」とは一体どんな番号なのか? - GIGAZINE

⇧ デバイスの電源がOFFになっていても、デバイスの追跡とかできるんかね?

PostgreSQLのデータベースの文字セットについて調べてみる

とりあえず、UTF8にしておけば良いと思ったのだけど、詳しく調べたことなかったなと思ったので、調べてみる。

日本語化されたPostgreSQL 公式のドキュメントによると、

www.postgresql.jp

24.3. 文字セットサポート

PostgreSQLの文字セット(エンコーディングとも呼ばれます)サポートにより、ISO 8859シリーズなどのシングルバイト文字やEUC(拡張Unixコード)、UTF-8Mule内部コードなどのマルチバイト文字を含む、各種文字セットでテキストを保存できます。 

https://www.postgresql.jp/docs/15/multibyte.html

全ての文字セットはクライアントにより透過的に使用できますが、いくつかは、サーバ内での(つまりサーバサイドエンコーディングとして)使用はサポートされていません。デフォルトの文字セットは、initdbを使用したPostgreSQLデータベースクラスタの初期化時に決定されます。 これは、データベースを作成する時に上書きできるので、異なる文字セットを使用した複数のデータベースを持つことができます。

https://www.postgresql.jp/docs/15/multibyte.html

⇧ とのこと。

分かり辛いのだけど、

cosol.jp

Oracle Databaseと同じく、PostgreSQL ではデータベース作成時にしか文字セットを指定できず、後から変更ができないということで良いかと。

PostgreSQLでデータベースを作成する時のオプションはと言うと、

www.postgresql.jp

CREATE DATABASE name
    [ WITH ] [ OWNER [=] user_name ]
           [ TEMPLATE [=] template ]
           [ ENCODING [=] encoding ]
           [ STRATEGY [=] strategy ] ]
           [ LOCALE [=] locale ]
           [ LC_COLLATE [=] lc_collate ]
           [ LC_CTYPE [=] lc_ctype ]
           [ ICU_LOCALE [=] icu_locale ]
           [ LOCALE_PROVIDER [=] locale_provider ]
           [ COLLATION_VERSION = collation_version ]
           [ TABLESPACE [=] tablespace_name ]
           [ ALLOW_CONNECTIONS [=] allowconn ]
           [ CONNECTION LIMIT [=] connlimit ]
           [ IS_TEMPLATE [=] istemplate ]
           [ OID [=] oid ]    

⇧ となっている。

基本的には、

 それによると、PostgreSQL 8.3以降でJIS X 0213:2004をUTF_8にてサポートしていて、EUC_JIS_2004やSHIFT_JIS_2004というエンコーディング名において相互変換できるようになっているそうだ。

JIS X 0208とJIS X 0213 – @tt-az on Tumblr

 サーバー側エンコーディングがUTF_8であれば、クライアント側エンコーディングEUC_JPやSJISやUTF_8はもちろん、SHIFT_JIS_2004も使えるとのこと。

JIS X 0208とJIS X 0213 – @tt-az on Tumblr

⇧ENCODINGをUTF_8にしておくしか無さそう。

あとは、LOCALEなんだけど、

⇧ いまいち、PostgreSQL のデータベースにおける文字セット、LOCALE、ENCODINGの用語の関係性がハッキリしない...

24.3. 文字セットサポート

PostgreSQLの文字セット(エンコーディングとも呼ばれます)サポートにより、ISO 8859シリーズなどのシングルバイト文字やEUC(拡張Unixコード)、UTF-8Mule内部コードなどのマルチバイト文字を含む、各種文字セットでテキストを保存できます。 

https://www.postgresql.jp/docs/15/multibyte.html

encoding

新しいデータベースで使われる文字セット符号化方式です。 文字列定数(例えば'SQL_ASCII')、整数の符号化方式番号、DEFAULTのいずれかを指定します。 DEFAULTとすると、デフォルトの符号化方式(すなわちテンプレートデータベースの符号化方式)を使います。 PostgreSQLサーバでサポートされる文字セットについては24.3.1で説明します。 この他の制限については後述します。

https://www.postgresql.jp/docs/15/sql-createdatabase.html

⇧ なるほど、ドキュメント内で用語の意味合いが異なるらしく、

ってことになるらしい。

で、PostgreSQL のデータベースにおけるLOCALEはと言うと、

 
locale

これはLC_COLLATELC_CTYPEを一度に設定する手っ取り早い方法です。

https://www.postgresql.jp/docs/15/sql-createdatabase.html

⇧ とあり、

 
lc_collate

新しいデータベースで使用する照合順(LC_COLLATE)です。 これは、たとえばORDER BYを持つ問い合わせなどにおいて文字列に適用されるソート順やテキスト型の列に対するインデックスで使用される順序に影響します。

https://www.postgresql.jp/docs/15/sql-createdatabase.html

 
lc_ctype

新しいデータベースで使用する文字のクラス(LC_CTYPE)です。 これは、たとえば小文字、大文字、数字といった文字の分類に影響します。 デフォルトではテンプレートデータベースの文字クラスを使用します。 さらなる制限に関しては後で説明します。

https://www.postgresql.jp/docs/15/sql-createdatabase.html

⇧ とあるのだけど、ソート順とかが関係してきますと。

少し、話が脱線するのですが、

www.postgresql.jp

initdbPostgreSQLのデータベースクラスタを新しく作成します。 データベースクラスタとは、1つのサーバインスタンスで管理されるデータベースの集合です。

https://www.postgresql.jp/docs/15/app-initdb.html

⇧と言う説明があり、公式のドキュメントではないのだけど、

medium.com

⇧ 上記サイト様のイメージ図を見た感じでは、

  1. initdb
    →データベースクラスターを作成する
  2. CREATE DATABASE
    →データベースを作成する

ってことになるかと。

一応、各々のデータベース(CREATE DATABASEを実行して作る方)で文字セットは変えることはできるのだけど、作成時にしか指定できず、後からの変更が不可であると、「株式会社コーソル」の方のサイトで仰っておりましたな。

で、PostgreSQL におけるLOCALEの話に戻ると、

www.postgresql.jp

24.1. ロケールのサポート

ロケールのサポートはアルファベット、並び換え、数字の書式など文化的嗜好を配慮したあるアプリケーションを対象にします。 PostgreSQLは、サーバのオペレーティングシステムが提供する、標準ISO CとPOSIXロケール機能を使用します。 これ以上の情報についてはお使いのシステムのドキュメントを参照ください。

https://www.postgresql.jp/docs/15/locale.html

英語の照合順序規則でスペイン語のメッセージを使用する時など、時として複数のロケールの規則を併用すると便利です。 これをサポートするために、ロケールには以下のような多言語対応規則の特定の箇所だけを管理する一連のサブカテゴリがあります。

https://www.postgresql.jp/docs/15/locale.html

一部のロケールカテゴリでは、その値がデータベース生成時に固定されていなければならないものがあります。 他のデータベースで他の設定を使用することができますが、一度データベースが生成されると、そのデータベースでは変更することができません。 LC_COLLATELC_CTYPEがこれらのカテゴリにあてはまります。 これらはインデックスのソート順に影響を及ぼすため、固定されていなければなりません。 さもないと、テキスト型の列上のインデックスは破壊されるでしょう。 (しかし24.2内で述べられているように、照合順序を使用することで、この制限を緩和できます)

https://www.postgresql.jp/docs/15/locale.html

 initdbが実行された時に、これらのカテゴリのデフォルト値は決定され、CREATE DATABASEコマンドで他を指定しない限り、新しいデータベースが作成されるときにこの値が使用されます。

https://www.postgresql.jp/docs/15/locale.html

その他のロケールカテゴリは、いつでも、ロケールカテゴリと同じ名前の実行時パラメータを設定することで、希望値に変更できます (詳細は20.11.2を参照してください)。 initdbで選択された値は、実際のところ、サーバの起動時にデフォルトとして動作するようにpostgresql.conf設定ファイルに書き込まれるだけです。 この代入文をpostgresql.confから削除すると、サーバは実行環境の設定をそのまま使用します。

https://www.postgresql.jp/docs/15/locale.html

⇧ 何やら、initdbで選択された値は、postgresql.confで変更できるような書きっぷりがある...

データベースクラスターの方の設定は、後から変更が可能ってことですかね?

ちなみに、PostgreSQL のデータベースにおけるLOCALEについて、

qiita.com

⇧ 上記サイト様がまとめて下さっておりました。

SQLでソートしたい値として、日本語があるような要件が必要とされる場合は、LOCALEとして「ja_JP.UTF8」を指定する感じになるんかね?

ちなみに、

yamap55.hatenablog.com

  • Linuxでは(バージョンとかディストリビューションで違いがあるかは知らない)デフォルトでは ja_JP.UTF-8 がないようなのでPostgreSQLの設定だけ行っても起動時にエラーとなる。
    • ↑のDockerfileに書いたようにlocaledefで追加する必要がある

PostgreSQLのデフォルトLOCALEでは日本語文字列のソート結果が想定と異なる - 山pの楽しいお勉強生活

⇧ 上記サイト様によりますと、そもそも、サーバー自体(Linuxとか)が、対応していないこともあるそうな。

気になるのは、

  • JIS X 0213
    • 第1面
      JIS X 0208の非漢字,JIS第1,2,3水準漢字
    • 第1面
      →第2面には第4水準漢字

⇧ このあたりのソートにも対応してるのか?

一応、

www.insight-ltd.co.jp

⇧ 上記サイト様によりますと、漢字もソートの対象となっているような感じではあるのですが、ハッキリとは分からない。

とりあえす、CREATE DATABASEする際は、ENCODINGとしては、明示的にUTF-8にしておいた方が良そうな気はしますかね。

毎度モヤモヤ感が半端ない…

今回はこのへんで。