8.4. バイナリ列データ型

byteaデータ型はバイナリ列の保存を可能にします。 表8-6を参照してください。

表 8-6. バイナリ列データ型

型名格納サイズ説明
bytea1または4バイトと実際のバイナリ列の長さ可変長のバイナリ列

バイナリ列はオクテット(またはバイト)の連続です。 バイナリ列は2つの方法で文字列と区別されます。 1点目は、バイナリ列はゼロの値のオクテットと他の"表示できない"オクテット(通常32から126の範囲外のオクテット)を保存できるということです。 文字列ではゼロというオクテットは使用できません。 また、データベースで選択している文字セット符号化方式で無効なオクテット値やオクテット値の並びも使用できません。 2点目は、バイナリ列を演算すると実際のバイトが処理されるのに対して、文字列の処理はロケール設定に従うということです。 まとめると、バイナリ列はプログラマが"バイト列そのもの"と考えるものを格納するのに適し、文字列はテキストを格納するのに適しています。

bytea型は入出力用に2つの外部書式をサポートします。 PostgreSQLの歴史的な"エスケープ"書式と"hex"です。 入力ではこれらの両方とも常に受け入れられます。 出力書式はbytea_output設定パラメータに依存し、デフォルトではhexです。 (hex書式はPostgreSQL 9.0から導入されたものであることに注意してください。 以前のバージョンや一部のツールではこれを理解しません。)

標準SQLは、BLOBまたはBINARY LARGE OBJECTという、異なるバイナリ列型を定義します。 入力書式はbyteaと異なりますが、提供される関数および演算子はほぼ同じです。

8.4.1. bytea hex書式

"hex"書式ではバイナリデータをバイト単位で上位の1/2バイトを先頭に2桁の16進数に符号化します。 (エスケープ書式と区別するために)文字列全体は\xという並びの後に付けられます。 一部の文脈では、エスケープ書式でバックスラッシュを二重にしなければならない一部の場合において、先頭のバックスラッシュを二重にしてエスケープさせる必要があるかもしれません。 詳細に付いては後で説明します。 16進数の桁は大文字でも小文字でも構いません。 桁の組み合わせと次の組み合わせの間に空白文字を入れることができます。 (しかし桁の組み合わせの間や先頭の\xの間には入れることはできません。) hex書式は外部のアプリケーションおよびプロトコルの間で広く互換性を持ち、また、エスケープ書式と比べ変換が高速になる傾向があります。 このため使用が好まれます。

SELECT E'\\xDEADBEEF';

8.4.2. byteaエスケープ書式

"エスケープ"書式はbytea型用の伝統的なPostgreSQLの書式です。 これは、バイナリ列をASCII文字の並びとして表現しASCII文字として表現できないバイトは特殊なエスケープシーケンスとして表現するという方式を取ります。 アプリケーションの見地から文字として表現されたバイトが有意であれば、この表現は簡便です。 しかし現実にはバイナリ列と文字列の間の区別があいまいになりますので、通常は混乱します。 また特に選択されたエスケープ機構は多少非効率的です。 このためこの書式はおそらくほとんどの新しいアプリケーションでは避けるべきでしょう。

エスケープ書式でbytea値を入力する際に、特定の値のオクテットをエスケープする必要があります。 なお、すべてのオクテットの値をエスケープすることができます。 一般的にあるオクテットをエスケープするには、それをその3桁の8進番号に変換し、バックスラッシュ(エスケープ文字列構文を使用してリテラルとして値を記述する場合は2つのバックスラッシュ)を前に付けます。 他にもバックスラッシュ自体(オクテット値92)を二重のバックスラッシュとして表現することができます。 表8-7には、エスケープする必要がある文字と、その適用可能な代替エスケープシーケンスを示しています。

表 8-7. オクテットをエスケープしたbyteaリテラル

10進オクテット値説明エスケープされた入力表現出力表現
0ゼロオクテットE'\\000'SELECT E'\\000'::bytea;\000
39単一引用符''''もしくはE'\\047'SELECT E'\''::bytea;'
92バックスラッシュE'\\\\'もしくはE'\\134'SELECT E'\\\\'::bytea;\\
0 to 31 and 127 to 255"表示できない"オクテットE'\\xxx' (8進数)SELECT E'\\001'::bytea;\001

実際には、表示できないオクテットに対するエスケープ要求はロケールの設定に依存して変化します。 インスタンスによっては、エスケープをしないで済むこともあります。 表8-7の例の各結果は、出力表現が時として1文字以上であっても、長さは正確に1オクテットであることに注意してください。

表8-7で示したように、複数バックスラッシュが必要な理由は、文字列リテラルとして記述された入力文字列は、PostgreSQLサーバ上で2つの解析段階を通過する必要があることです。 各組み合わせの最初のバックスラッシュは文字列リテラル用パーサでエスケープ文字と解釈(エスケープ文字列構文の使用を前提)され、2番目のバックスラッシュを残して、そこで消費されます。 (この段階のエスケープを避けるためにドル引用符による文字列を使用することができます。) 残りのバックスラッシュは、bytea入力関数が3桁のオクテット値の先頭に付く記号、もしくは、他のバックスラッシュをエスケープする記号として認識します。 例えば、E'\\001'としてサーバに渡された文字列リテラルは、エスケープ文字列パーサを通過した後\001のようになります。 \001はその後bytea入力関数に送られ、10進数値1の1つのオクテットに変換されます。 単一引用符文字はbyteaでは特別に扱われず、通常の文字列リテラルの規則に従うことに注意してください。 (項4.1.2.1も参照してください。)

また、Byteaオクテットは出力時も時々エスケープされます。 一般的には、各"表示できない"オクテットは、1つのバックスラッシュの後に等価な3桁8進数という形に変換されます。 ほとんどの"表示できる"オクテットは、クライアント文字セットにおける標準表現で表されます。 10進数で92となるオクテット(バックスラッシュ)は出力では二重になります。 詳細は表8-8に示します。

表 8-8. bytea出力のエスケープされたオクテット

10進オクテット値説明エスケープされた出力表現出力結果
92バックスラッシュ\\SELECT E'\\134'::bytea;\\
0から31および127から255"表示できない"オクテット\xxx(8進数)SELECT E'\\001'::bytea;\001
32から126"表示できる"オクテットクライアント文字セットにおける表現SELECT E'\\176'::bytea;~

使用するPostgreSQLのフロントエンドによっては、bytea文字列をエスケープまたはアンエスケープする際に、追加的な作業が必要になることがあります。 例えば、使用するインタフェースが改行文字や復帰文字を自動的に翻訳してしまう場合、これらの文字もエスケープしなければならないかもしれません。