ほとんどのデータベースシステムは生データを格納できるデータ型を提供しており、PostgreSQLも例外ではありません。 私は、データベースが値の構造や意味を理解していないことを意味するために生データという用語を使用します。 対照的に、PostgreSQLは他のデータ型の構造と意味を理解しています。 たとえば、整数列を定義すると、PostgreSQLは、その列に配置するデータのバイトが整数値を表すことになっていることを認識します。 PostgreSQLは整数が何であるか知っていますか?整数を追加したり、それらを乗算したり、文字列形式との間で変換したりすることができます。 一方、生データは単なるビットの集まりですか?PostgreSQLはデータの意味を推測することはできません。

PostgreSQLは、生データを格納するためのタイプBYTEAを提供しています。 BYTEA列は理論的には任意の長さの値を保持できますが、最大長は1GBであるようです。

BYTEA値のサイズは、4バイトに値の実際のバイト数を加えたものです。

リテラル値の構文

BYTEA値を入力するのは少し難しいかもしれません。 BYTEAリテラルは文字列リテラルとして入力されます:これは単なる一重引用符で囲まれた文字の文字列です。 それを考えると、単一引用符を含むBYTEA値をどのように入力しますか? 文字列リテラル値の説明(この章の前半)を振り返ると、文字列値に特殊文字をエスケープすることで特殊文字を含めることができることがわかります。 特に、単一引用符は、次のいずれかの方法でエスケープすることができます:

  • 一重引用符をダブルアップします(‘これは一重引用符です”‘)

  • 単一引用符の前に円記号を付けます(‘これは単一引用符です\”)

  • 代わりに文字の8進数値を含めます(‘これは単一引用符です\047’)

BYTEAリテラルを入力するときにエスケープする必要がある他の二つの文字があります。 値がゼロのバイト(文字0ではなく、ヌルバイト)はエスケープする必要があり、バックスラッシュ文字はエスケープする必要があります。 “\\Ddd”形式を使用して任意の文字をエスケープできます(dddは8進数です)。 “\\C”形式を使用して、印刷可能な文字をエスケープすることができます。 したがって、ゼロバイトを含むBYTEA値を格納する場合は、次のように入力できます:

'This is a zero byte \000'

バックスラッシュを含むBYTEA値を格納する場合は、次のいずれかの形式で入力できます:

'This is a backslash \\''This is also a backslash \134'

これらのルールを文字列リテラルを引用するためのルールと比較すると、BYTEAリテラルには2倍のバックスラッシュ文字が必要であることがわかります。 これはPostgreSQLパーサーの設計の癖です。 BYTEAリテラルは二つの異なるパーサーによって処理されます。 メインのPostgreSQLパーサーは、BYTEAリテラルを文字列リテラルとして認識します(バックスラッシュ文字の最初のセットをゴブリング)。 次に、BYTEAパーサーは結果を処理し、バックスラッシュ文字の第二のセットをゴブリングします。

したがって、このようなBYTEA値がバックスラッシュ\である場合は、’This is a backslash\\\\’として引用します。 文字列パーサーがこの文字列を処理した後、’This is a backslash\\’に変換されました。 BYTEAパーサーは最終的にこれを円記号\に変換します。

サポートされている演算子

PostgreSQLは単一のBYTEA演算子を提供しています:連結。 連結(||)演算子を使用して、あるBYTEA値を別のBYTEA値に追加できます。

等価/不等式であっても、2つのBYTEA値を比較することはできないことに注意してください。 もちろん、CAST()演算子を使用してBYTEA値を別の値に変換することができ、他の演算子を開くことができます。

ラージオブジェクト

BYTEAデータ型は、現在、1GB以下の値を格納することに制限されています。 BYTEA列に収まるよりも大きな値を格納する必要がある場合は、large-objectsを使用できます。 ラージオブジェクトは、テーブルの外部に格納されている値です。 たとえば、tapesテーブルの各行に写真を格納する場合は、対応するラージオブジェクトへの参照を保持するOID列を追加します:

movies=# ALTER TABLE tapes ADD COLUMN photo_id OID;ALTER

photo_id列の各値は、pg_largeobjectシステムテーブルのエントリを参照します。 PostgreSQLには、外部ファイル(JPEGファイルなど)をpg_largeobjectテーブルにロードする関数が用意されています:

movies=# INSERT INTO tapes VALUESmovies-# (movies(# 'AA-55892',movies(# 'Casablanca',movies(# lo_import('/tmp/casablanca.jpg' )movies(# );

lo_import()関数は、指定されたファイルをpg_largeobjectにロードし、ラージオブジェクトを参照するOID値を返します。 この行を選択すると、写真を構成する実際のビットではなく、OIDが表示されます:

movies=# SELECT * FROM tapes WHERE title = 'Casablanca'; tape_id | title | photo_id----------+------------+---------- MC-68873 | Casablanca | 510699

写真をファイルに書き戻したい場合は、lo_export()関数を使用できます:

movies=# SELECT lo_export( 510699, '/tmp/Casablanca.jpg' ); lo_export----------- 1(1 row)

現在のデータベース内のすべてのラージオブジェクトを表示するには、psqlの\lo_listメタコマンドを使用します:

movies=# \lo_list Large objects ID | Description--------+------------- 510699 |(1 row)

データベースからラージオブジェクトを削除するには、lo_unlink()関数を使用します:

movies=# SELECT lo_unlink( 510699 ); lo_unlink----------- 1(1 row)movies=# \lo_list Large objects ID | Description----+-------------(0 rows)

参照OIDの背後にある実際のビットにはどのように到達しますか? できないの?少なくともpsqlではそうではありません。 ラージオブジェクトサポートは、使用しているクライアントアプリケーションに組み込まれている必要があります。 psqlはテキスト指向のツールであり、写真を表示する方法がないため、pg_largeobjectテーブルの生データを見るのが最善です。 Conjectrixワークステーションなどのいくつかのクライアントアプリケーションは、ラージオブジェクトをサポートし、ほとんどの場合、生データを適切に解釈