PostgreSQLにはユーザが使用可能な豊富なデータ型が始めから備わっています。 CREATE TYPEコマンドでPostgreSQLに対し新しいデータ型を追加できます。
表8-1に組み込みの汎用データ型をすべて示します。 "別名"欄に列挙された代替名称のほとんどは、歴史的な理由によりPostgreSQL の内部で使用されている名前です。 他にも、ここに記載していない、内部で使用されるデータ型、削除予定のデータ型もあります。
表 8-1. データ型
名称 | 別名 | 説明 |
---|---|---|
bigint | int8 | 8バイト符号付整数 |
bigserial | serial8 | 自動増分8バイト整数 |
bit | 固定長ビット列 | |
bit varying(n) | varbit(n) | 可変長ビット列 |
boolean | bool | 論理(ブール)値(真/偽) |
box | 平面上の矩形 | |
bytea | バイナリデータ | |
character varying(n) | varchar(n) | 可変長文字列 |
character(n) | char(n) | 固定長文字列 |
cidr | IPv4もしくはIPv6ネットワークアドレス | |
circle | 平面上の円 | |
date | 暦の日付(年月日) | |
double precision | float8 | 倍精度浮動小数点 |
inet | IPv4もしくはIPv6ホストアドレス | |
integer | int, int4 | 4バイト符号付整数 |
interval(p) | 時間間隔 | |
line | 平面上の無限直線(完全に実装されていません) | |
lseg | 平面上の線分 | |
macaddr | MAC アドレス | |
money | 貨幣金額 | |
numeric [ (p, s) ] | decimal [ (p, s) ] | 精度の選択可能な高精度数値 |
path | 平面上の経路(開経路および閉経路) | |
point | 平面上の幾何学的点 | |
polygon | 平面上の閉じた幾何学的経路 | |
real | float4 | 単精度浮動小数点 |
smallint | int2 | 2 バイト符号付整数 |
serial | serial4 | 自動増分 4 バイト整数 |
text | 可変長文字列 | |
time [ (p) ] [ without time zone ] | 時刻 | |
time [ (p) ] with time zone | timetz | 時間帯付き時刻 |
timestamp [ (p) ] without time zone | timestamp | 日付と時刻 |
timestamp [ (p) ] [ with time zone ] | timestamptz | 時間帯付き日付と時刻 |
互換性: 次に挙げるデータ型(あるいはその綴り方)はSQL で規定されています。 bit、bit varying、boolean、char、 character varying、character、varchar、 date、double precision、integer、 interval、numeric、decimal、real、 smallint、time(タイムゾーン付き、無しの両方)、 timestamp(タイムゾーン付き、無しの両方)。
それぞれのデータ型にはそのデータ型の入出力関数で決定される外部表現を保有しています。 組み込みデータ型の多くには、はっきりとした外部書式があります。 とはいっても、開経路、もしくは閉経路のようなPostgreSQLに特有な型や、あるいは、日付や時刻データ型のように書式をいくつか選択できる型が多くあります。 一部の入出力関数は転置することができません。 つまり、出力関数による結果は最初の入力と比較した場合精度を失う可能性があります。
(足し算や掛け算などの)演算子と関数には、実行速度を上げるために実行時にエラーチェックを行わないものもあります。 例えば、システムによっては、あるデータ型に対する数値演算子が知らないうちにアンダーフローやオーバーフローを引き起こすかもしれません。
数値データ型には2、4、8バイト整数と、4、8バイト浮動小数点および固定精度数があります。 表8-2に使用可能な型を列挙します。
表 8-2. 数値データ型
型名 | 格納サイズ | 説明 | 範囲 |
---|---|---|---|
smallint | 2バイト | 狭範囲の整数 | -32768から+32767 |
integer | 4バイト | 通常使用する整数 | -2147483648から+2147483647 |
bigint | 8バイト | 広範囲整数 | -9223372036854775808から9223372036854775807 |
decimal | 可変長 | ユーザ指定精度、正確 | 最大1000桁[訳注:原文ではno limitです] |
numeric | 可変長 | ユーザ指定精度、正確 | 最大1000桁[訳注:原文ではno limitです] |
real | 4バイト | 可変精度、不正確 | 6桁精度 |
double precision | 8バイト | 可変精度、不正確 | 15桁精度 |
serial | 4バイト | 自動増分整数 | 1から2147483647 |
bigserial | 8バイト | 広範囲自動増分整数 | 1から9223372036854775807 |
数値データ型に対する定数の構文は項4.1.2で説明されています。 数値データ型には対応する算術演算子と関数の一式が揃っています。 詳細は第9章を参照してください。 次節でデータ型について詳しく説明します。
smallint、integer、bigintは数詞全体を保持します。 その意味は小数点以下の端数や、変化に富む数値の範囲を保持しません。 許容範囲に外れた値を保存しようとするとエラーになります。
integer型は数値の範囲、保存のサイズおよび性能において最も釣合いが取れているので、通常使用されます。 smallint型は一般的にディスク容量に制限がついている場合にのみ使用します。 bigint型はintegerが許容する範囲では充分ではない場合にのみ使用すべきです。 integerデータ型の方がずっと速いからです。
8バイト整数をコンパイラがサポートしているかに依存するbigint型は、すべてのプラットフォームで正常に機能するとは限りません。 サポートしていないマシン上ではbigintはintegerと同じに振舞います(しかし、領域は8バイトまで必要です)。 しかしながら、このようなことが現実の問題を起こすようなプラットフォームがあるかどうか判りません。
SQLでは整数の型としてinteger(またはint)とsmallintのみを規定しています。 bigintとint2、int4、および int8は拡張ですが、他の様々なSQLデータベースシステムでも使われています。
注意: インデックスが付けられたsmallintあるいはbigintの列がテーブルにある場合、システムがそのインデックスを使用しようとした時に問題を引き起こすことがあります。 例えば句が次のような形式の場合、
... WHERE smallint_column = 42システムはインデックスを使用しません。 なぜなら42という定数にシステムがintegerを割り当てるからです。 今の所PostgreSQLは2つの異なるデータ型が混在している時には、インデックスを使うことができません。 問題を回避するには以下のように定数部分を単一引用符で括ります。
... WHERE smallint_column = '42'こうすると、システムは型分析を後廻しにしてこの定数に正しいデータ型を割り振ります。
numeric型は、最大1000桁の精度で数値を格納でき、正確な計算を行えます。 通貨金額やその他正確性が求められる数量を保存する時は特にこの型を推奨します。 とはいっても、numericは次節で説明する浮動小数点データ型に比較し動作が非常に遅くなります。
この後の説明では、次の用語を使用します。 numericの位取りとは小数点の右側の小数点以下の桁数をいいます。 numericの精度とは数字全体の有効桁数です。 すなわち、小数点をはさんでいる両側の桁数の合計です。 そのため、23.5141という数値の精度は6で位取りは4となります。 整数の位取りは、ゼロであると見なすことができます。
数値の精度と位取りは共に定義することができます。 列のデータ型をnumericと宣言するには次の構文を使います。
NUMERIC(precision, scale)
精度は正数、位取りは0もしくは正数でなければなりません。 他に
NUMERIC(precision)
は位取りが0であることを選択します。
NUMERIC
精度または位取りの指定がない場合、精度が実装されている限界までは、いかなる精度あるいは位取りの値も格納できる列が作られます。 この類の列はいかなる特定の位取りに対しても入力値を強要しませんが、宣言された位取りを持つnumeric列は入力値にその位取りを強要します。 (標準SQLはデフォルトとして位取り0を要求していて、整数に対する厳密性を強制しています。 しかし、この方法は、あまり役に立たないと思われます。 もし移植性を心配するなら常に精度と位取りを明示的に設定してください。)
宣言された列の精度または位取りより、値の精度または位取りが大きい場合、システムが値を丸めようとします。 もし宣言された範囲内で丸めることができない時はエラーとなります。
decimalとnumeric型は等価です。 2つのデータ型は共に標準SQLに従っています。
realとdouble precisionは不正確な精度が変動する数値データ型です。 実際にはこれらのデータ型は、使用しているプロセッサ、オペレーティングシステムおよびコンパイラがサポートしていれば、通常は(それぞれ単精度および倍精度の)バイナリ浮動小数点演算のためのIEEE規格754の実装です。
不正確というのは、ある値はそのままで内部形式に変換されずに近似値として保存されます。 ですから、保存しようとする値と保存された値を戻して表示した場合に多少の差異が認められます。 これらのエラーを管理し計算によって補正をどうするかは数学の系統全部とコンピュータ科学にかかわることで、ここではこの先について以下の点を除き触れません。
(金銭金額など)正確な記録と計算が必要な時はnumericをその代わりとして使います。
これらのデータ型で何か重要な件に対し複雑な計算を必要とする時、特に(無限大とかアンダーフローのような)境界線におけるある種の振舞いについて信頼を置かなければならないのであれば、実装を注意深く検証しなければなりません。
2つの浮動小数点値が等価であるのかどうかの比較は予想通りに行く時もあれば行かない時もあります。
ほとんどのプラットフォームではrealは最低6桁の精度を持った少なくとも-1E+37と+1E+37の範囲です。 double precisionは通常最低15桁の精度でおよそ-1E+308と+1E+308の範囲です。 大き過ぎたり小さ過ぎる値はエラーの原因となります。 入力値の精度が高すぎる場合は丸められることがあります。 ゼロに限りなく近い値で、しかもゼロとは区別されているように見なされない数値はアンダーフローエラーを引き起こします。
また、PostgreSQLでは不正確な数値型を規定する標準SQLのfloatとfloat(p)をサポートしています。 ここで、pは2進数の桁数で最低受け付ける精度を指定します。 PostgreSQLはfloat(1)からfloat(24)をrealを選択するものとして受け付け、float(25)からfloat(53)をdouble precisionを選択するものとして受け付けます。 許容範囲外のpの値はエラーになります。 精度指定の無いfloatはdouble precisionとして解釈されます。
注意: 7.4より前のPostgreSQLでは、float(p)の精度は10進数桁数として解釈されました。 これは、2進数桁数の精度を規定する標準SQLに一致するように変更されたものです。 realとdouble precisionの仮数がそれぞれ24ビットと53ビットであるという前提はIEEE標準浮動小数点の実装では正しいものです。 非IEEEのプラットフォームでは、一部無効になる可能性がありますが、単純化のためにすべてのプラットフォームでpの範囲は同一です。
serialおよびbigserialデータ型は正確にはデータ型ではなく、テーブルの列に一意の識別子を設定する簡便な表記法です。 (他のデータベースでサポートされるAUTO_INCREMENTプロパティに似ています。) 現在の実装では、
CREATE TABLE tablename ( colname SERIAL );
は以下を指定することと同じです。
CREATE SEQUENCE tablename_colname_seq; CREATE TABLE tablename ( colname integer DEFAULT nextval('tablename_colname_seq') NOT NULL );
このように整数列を作成し、その列のデフォルト値が連番生成器から割り当てられるようにしました。 また、NOT NULL制約を適用することによって、null値が明示的に挿入されないようにします。 たいていの場合は、重複する値を間違って挿入しないように、UNIQUE制約またはPRIMARY KEY制約も追加することが推奨されますが、これは自動的には行われません。
注意: PostgreSQL 7.3より前では、serialはUNIQUEを意味していました。 現在では自動的には行なわれません。 連番の列に一意性制約もしくはプライマリキーを付与したい場合は、他のデータ型同様指定しなければなりません。
serial列にシーケンスの次の値を挿入するには、serial列にそのデフォルト値を割り当てるよう指定してください。 これは、INSERT文の列リストからその列を除外する、もしくは、DEFAULTキーワードを使用することで行なうことができます。
serialとserial4という型の名称は等価です。 共にinteger列を作成します。 bigserialとserial8という型の名称もbigint列を作成することを除いて同じ振舞いをします。 もしテーブルを使用する期間で231以上の識別子を使用すると予測される場合、bigserialを使用しなければいけません。
serial列用に作成されたシーケンスは、それを所有する列が削除された時に自動的に削除され、他の方法で削除されることはありません。 (このことは、PostgreSQLの7.3より前のバージョンには当てはまりません。 バージョン7.3より前のデータベースからのダンプをリロードすることによって作成されたシーケンスについては、この自動連鎖削除は発生しません。 それは、7.3より前のダンプファイルには、依存関係の繋がりを確立するために必要な情報が含まれていないからです。) 更に言えば、この依存関係はserial列によって生成されたシーケンスとこの列自体の間にだけ存在します。 もし他の列がこのシーケンスを参照していた(おそらくnextval()関数を手動で呼び出す)場合、このシーケンスが破棄されたらその関係は壊れてしまいます。 serial列のシーケンスをこのように使用することは好ましくないものとみなされています。 同一のシーケンス生成器から複数の列の値を提供したいのであれば、独立したオブジェクトとしてシーケンスを作成してください。