数値データ型には2、4、8バイト整数と、4、8バイト浮動小数点および精度設定が可能な数があります。 表 8.2に使用可能な型を列挙します。
表8.2 数値データ型
型名 | 格納サイズ | 説明 | 範囲 |
---|---|---|---|
smallint | 2バイト | 狭範囲の整数 | -32768から+32767 |
integer | 4バイト | 典型的に使用する整数 | -2147483648から+2147483647 |
bigint | 8バイト | 広範囲整数 | -9223372036854775808から+9223372036854775807 |
decimal | 可変長 | ユーザ指定精度、正確 | 小数点より上は131072桁まで、小数点より下は16383桁まで |
numeric | 可変長 | ユーザ指定精度、正確 | 小数点より上は131072桁まで、小数点より下は16383桁まで |
real | 4バイト | 可変精度、不正確 | 6桁精度 |
double precision | 8バイト | 可変精度、不正確 | 15桁精度 |
smallserial | 2バイト | 狭範囲自動整数 | 1から32767 |
serial | 4バイト | 自動増分整数 | 1から2147483647 |
bigserial | 8バイト | 広範囲自動増分整数 | 1から9223372036854775807 |
数値データ型に対する定数の構文は4.1.2で説明しています。 数値データ型には対応する算術演算子と関数の一式が揃っています。 詳細は第9章を参照してください。 次節でデータ型について詳しく説明します。
smallint
、integer
、bigint
は各種範囲の整数、つまり小数点以下の端数がない数を保持します。
許容範囲から外れた値を保存しようとするとエラーになります。
integer
型は数値の範囲、格納サイズおよび性能において最も釣合いが取れていますので、一般的に使用されます。
smallint
型は通常はディスク容量に制限が付いている場合にのみ使用します。
bigint
型はinteger
の許容範囲では十分ではない場合に使用されるよう設計されています。
SQLでは整数の型としてinteger
(またはint
)とsmallint
、bigint
のみを規定しています。
int2
、int4
およびint8
は拡張ですが、いくつか他のSQLデータベースシステムでも使われています。
numeric
型は、非常に大きな桁数で数値を格納できます。
通貨金額やその他正確性が求められる数量を保存する時は特に、この型を推奨します。
numeric
の値での計算は、可能なところ、例えば、足し算、引算、掛け算では、正確な結果(訳注:10進の小数で誤差が生じない、ということ)になります。
とは言っても、numeric
の値に対する計算は整数型、もしくは次節で説明する浮動小数点データ型に比較し非常に遅くなります。
この後の説明では、次の用語を使用します。
numeric
の精度(precision)とは数字全体の有効桁数です。
すなわち、小数点をはさんでいる両側の桁数の合計です。
numeric
の位取り(scale)とは、小数点の右側の小数部分の桁数をいいます。
そのため、23.5141という数値の精度は6で位取りは4となります。
整数の位取りは、ゼロであるとみなすことができます。
numeric
列の数値の最大精度と最大位取りの両方を設定することができます。
numeric
型の列を宣言するには次の構文を使います。
NUMERIC(precision
,scale
)
精度は正数、位取りは0もしくは正数でなければなりません。 他の記述方法として、
NUMERIC(precision
)
は位取りが0であることを選択します。 精度も位取りも指定せず、
NUMERIC
と記述すると、実装されている限界の精度まで、いかなる精度あるいは位取りの値も格納できる列が作られます。
この類の列は入力値をいかなる特定の位取りにも変換しませんが、宣言された位取りを持つnumeric
列は入力値をその位取りに変換します。
(標準SQLはデフォルトとして位取り0を要求していて、つまり、整数の精度に変換されます。
しかし、この方法はあまり役に立たないと思われます。
もし移植性を心配するなら、常に精度と位取りを明示的に設定してください。)
明示的に型宣言で指定される場合に許される最大精度は1000です。
精度の指定がないNUMERIC
は表 8.2で説明する制限に従います。
格納される値の位取りが宣言された列の位取りより大きかった場合、システムは指定された小数部の桁まで値を丸めます。 そして、小数点の左側の桁数が、宣言された精度から宣言された位取りを差し引いた数を超える場合にエラーとなります。
数値は物理的に先頭や末尾に0を付与されることなく格納されます。
したがって、列の宣言された精度と位取りは最大であり、固定的に割り当てられていません。
(この意味ではnumeric
はchar(
よりもn
)varchar(
に似ています。)
実際の格納に必要な容量は、10進数4桁のそれぞれのグループに対して2バイトと、3から8バイトのオーバヘッドです。
n
)
通常の数値に加え、numeric
型は、「非数値」を意味するNaN
という特別な値を取ることができます。
NaN
に対する操作はすべて、別のNaN
を生成します。
この値をSQLコマンドの定数として記述する場合は、例えばUPDATE table SET x = 'NaN'
のように、引用符でくくらなければなりません。
入力の際は、NaN
という文字列は大文字小文字の区別なく認識されます。
ほとんどの「非数」の概念の実装において、NaN
は(NaN
を含む)他の数値と等価にならないとみなされています。
numeric
値をソートできる、また、ツリーを基にしたインデックスで使用できるように、PostgreSQLはNaN
同士は等しく、すべてのNaN
以外の値よりも大きな値となるものとして扱います。
decimal
とnumeric
型は等価です。
2つのデータ型はともに標準SQLに含まれます。
値を丸める際、numeric
型は0から離れるように丸めますが、一方で(ほとんどのマシンでは)real
やdouble precision
型ではその値に最も近い偶数に丸めます。
以下に例を示します。:
SELECT x, round(x::numeric) AS num_round, round(x::double precision) AS dbl_round FROM generate_series(-3.5, 3.5, 1) as x; x | num_round | dbl_round ------+-----------+----------- -3.5 | -4 | -4 -2.5 | -3 | -2 -1.5 | -2 | -2 -0.5 | -1 | -0 0.5 | 1 | 0 1.5 | 2 | 2 2.5 | 3 | 2 3.5 | 4 | 4 (8 rows)
real
とdouble precision
は不正確な(訳注:10進の小数で誤差が生じる、ということ)可変精度の数値データ型です。
実際にはこれらのデータ型は、使用しているプロセッサ、オペレーティングシステムおよびコンパイラがサポートしていれば、通常は(それぞれ単精度および倍精度の)バイナリ浮動小数点演算用のIEEE規格754の実装です。
不正確というのは、ある値はそのままで内部形式に変換されずに近似値として保存されるということです。 ですから、保存しようとする値と抽出しようとする値の間に多少の差異が認められます。 これらのエラーを管理し計算によって補正をどうするかについては、数学とコンピュータ科学の系統すべてに関わることで、以下の点を除き触れません。
(金銭金額など)正確な記録と計算が必要な時は代わりにnumeric
を使用してください。
これらのデータ型で何か重要な件に対し複雑な計算を必要とする時、特に(無限大やアンダーフローのような)境界線におけるある種の振舞いについて信頼を置かなければならないのであれば、実装を注意深く検証しなければなりません。
2つの浮動小数点値が等価であるのかどうかの比較は予想通りに行かない時もあります。
ほとんどのプラットフォームではreal
は最低6桁の精度を持ち、少なくとも1E-37から1E+37までの範囲です。
double precision
は通常最低15桁の精度でおよそ1E-307から1E+308までの範囲です。
大き過ぎたり小さ過ぎる値はエラーの原因となります。
入力値の精度が高過ぎる場合は丸められることがあります。
ゼロに限りなく近い値で、しかもゼロと異なる値として表現できない数値はアンダーフローエラーを引き起こします。
浮動小数点を含む値が出力用のテキストに変換される場合、extra_float_digitsによって有効数字を制御します。
デフォルト値の0
が指定されている場合、出力はPostgreSQLをサポートする全てのプラットフォームで同じです。
この値を大きくすることで格納された値をより精密に表現できますが、プラットフォーム間の移植性が失われるかもしれません。
通常の数値に加え、浮動小数点型では以下の特殊な値を取ります。
Infinity
-Infinity
NaN
これらはそれぞれ、IEEE 754の特殊な値、「無限大」、「負の無限大」、「非数値」を表します。
(浮動小数点計算がIEEE 754に従わないマシンでは、これらの値はおそらく正しく動作しません。)
これらの値をSQLコマンドの定数として記述する場合、例えばUPDATE table SET x = '-Infinity'
のように引用符でくくる必要があります。
入力の際、これらの文字列は大文字小文字の区別なく認識されます。
IEEE754では、NaN
は(NaN
を含む)他のすべての浮動小数点値と比べた時に不等でなければならないと規定しています。
浮動小数点値をソートできる、また、ツリーを基にしたインデックスで使用できるように、PostgreSQLはNaN
同士は等しく、すべてのNaN
以外の値よりも大きな値となるものとして扱います。
また、PostgreSQLでは不正確な数値型についての標準SQLの表記であるfloat
とfloat(
をサポートしています。
ここで、p
)p
は2進数桁数で最低限、許容可能な精度を指定します。
PostgreSQLはfloat(1)
からfloat(24)
をreal
を選択するものとして受け付け、float(25)
からfloat(53)
をdouble precision
を選択するものとして受け付けます。
許容範囲外のp
の値はエラーになります。
精度指定のないfloat
はdouble precision
として解釈されます。
real
とdouble precision
の仮数がそれぞれ24ビットと53ビットであるという前提は、IEEE標準浮動小数点の実装では正しいものです。
非IEEEのプラットフォームでは、若干、異なる可能性がありますが、単純化のためにすべてのプラットフォームでp
の範囲は同一です。
このセクションではPostgreSQL固有の自動増分列の作成方法について記述します。 SQL標準の識別列を作成する方法は、CREATE TABLEに記述されています。
smallserial
、serial
およびbigserial
データ型は正確にはデータ型ではなく、テーブルの列に一意の識別子を作成する簡便な表記法です
(他のデータベースでサポートされるAUTO_INCREMENT
プロパティに似ています)。
現在の実装では、
CREATE TABLEtablename
(colname
SERIAL );
は以下を指定することと同じです。
CREATE SEQUENCEtablename
_colname
_seq; CREATE TABLEtablename
(colname
integer NOT NULL DEFAULT nextval('tablename
_colname
_seq') ); ALTER SEQUENCEtablename
_colname
_seq OWNED BYtablename
.colname
;
このように整数列を作成し、その列のデフォルト値が連番ジェネレータから割り当てられるようにしました。
また、NOT NULL
制約を適用することによって、NULL値が挿入されないようにします。
(たいていの場合は、重複する値を間違って挿入しないように、UNIQUE
制約またはPRIMARY KEY
制約も追加することになるでしょうが、これは自動的には行われません。)
最後に、シーケンスは列に「より所有」されるものと印が付きます。
したがって、テーブルの列が削除された場合にシーケンスは削除されます。
smallserial
、 serial
およびbigserial
はシーケンスを使って実装されているため、行の削除が行われていなくとも、列に"穴"や連番の抜けが発生するかもしれません。また、テーブルへ正常に挿入されていないにも関わらず、シーケンスの値を"消費してしまう"こともあります。これは、例えば挿入したトランザクションがロールバックされた時に発生することがあります。詳細は9.16のnextval()
を参照してください。
serial
列にシーケンスの次の値を挿入するには、serial
列にそのデフォルト値を割り当てるよう指定してください。
これは、INSERT
文の列リストからその列を除外する、もしくはDEFAULT
キーワードを使用することで行うことができます。
serial
とserial4
という型の名称は等価です。
ともにinteger
列を作成します。
bigserial
とserial8
という型の名称もbigint
列を作成することを除いて同じ振舞いをします。
もしテーブルを使用する期間で231以上の識別子を使用すると予測される場合、bigserial
を使用すべきです。
smallserial
とserial2
という型の名称もまた、smallint
列を作成することを除いて同じ振舞いをします。
serial
列用に作成されたシーケンスは、それを所有する列が削除された時に自動的に削除されます。
列を削除せずにシーケンスを削除することができますが、これにより強制的に列のデフォルト式が削除されます。