全てのテーブルには、システムによって暗黙的に定義されたシステム列がいくつかあります。 そのため、システム列の名前はユーザ定義列の名前として使うことはできません。 (これらの制約は名前がキーワードであるかどうかとは関係ありません。 つまり、名前を引用符で囲んでもこの制約を回避することはできません。) システム列については、あまり意識する必要はありません。 これらが存在することを知っていれば十分です。
oid
行のオブジェクト識別子(オブジェクトID)です。
この列はWITH OIDS
を付けてテーブルが作成された場合、あるいはテーブル作成時にdefault_with_oids設定変数が設定されていた場合にのみ存在します。
この列の型はoid
(列名と同じ)です。この型についての詳細は8.18を参照してください。
tableoid
この行を含むテーブルのOIDです。
この列は特に、継承階層からの選択問い合わせでは便利です(5.9を参照してください)。
この列がないと、どのテーブルからその行が来たのかわかりにくいからです。
tableoid
をpg_class
のoid
列に結合することでテーブル名を得ることができます。
xmin
この行バージョンの挿入トランザクションの識別情報(トランザクションID)です。 (行バージョンとは、行の個別の状態です。 行が更新される度に、同一の論理的な行に対する新しい行バージョンが作成されます。)
cmin
挿入トランザクション内の(0から始まる)コマンド識別子です。
xmax
削除トランザクションの識別情報(トランザクションID)です。 削除されていない行バージョンではゼロです。 可視の行バージョンでこの列が非ゼロの場合があります。 これは通常、削除トランザクションがまだコミットされていないこと、または、削除の試行がロールバックされたことを意味しています。
cmax
削除トランザクション内のコマンド識別子、もしくはゼロです。
ctid
テーブル内における、行バージョンの物理的位置を表します。
ctid
は行バージョンを素早く見つけるために使うことができますが、行のctid
はVACUUM FULL
により更新あるいは移動させられると変わります。
したがって、ctid
は長期の行識別子としては使えません。
論理行を識別するためには、OID、あるいはさらに良いのはユーザ定義の通番数を使うべきです。
OIDは32ビット数であり、クラスタ全体で1つのカウンタです。 大規模、もしくは長期間使用するデータベースでは、カウンタが一周してしまう可能性があります。 そのため、一意性を確保するための手順を踏んでいない限り、OIDが一意であると仮定してはなりません。 もしテーブル内の行を同定する必要がある場合は、シーケンスジェネレータを使用することを強く推奨します。 しかし、OIDはいくつかの注意を払うことによりシーケンスと同様に使用することができます。
OIDを行の特定のために使用するテーブルについては、OID列に一意性制約を作成するべきです。 このような一意性制約(もしくは一意インデックス)が存在する場合は、システムは既存の行に一致するようなOIDを生成しません。 (もちろん、これはテーブルの行数が232(40億)より少ない場合に可能となります。性能を考慮すると、実際には行数はそれよりずっと少ない方がよいでしょう。)
OIDは複数のテーブルをまたがって一意であると仮定してはなりません。
データベース全体での識別子が必要な場合はtableoid
と行OIDを組み合わせて使用してください。
もちろん、問題にしているテーブルは、WITH OIDS
を使用して作成されなくてはいけません。
PostgreSQL 8.1からWITHOUT OIDS
がデフォルトです。
トランザクション識別子も32ビット量です。 長期間使用するデータベースでは、トランザクションIDが一周してしまう可能性があります。 これは、適切な保守作業を行うことで、致命的な問題にはなりません。 詳細は第24章を参照してください。 しかし、長期(10億トランザクション以上)にわたってトランザクションIDの一意性に依存することは賢明ではありません。
コマンド識別子もまた、32ビット量です。 このため、単一トランザクション内のコマンド数には232(40億)個までという制限が発生します。 実際、この制限は問題にはなりません。 これはSQLコマンド数に対する制限であり、処理される行数に対する制限ではないことに注意してください。 また、データベースの内容を実際に変更するコマンドのみがコマンド識別子を消費します。