8.1. 数値データ型 #

数値データ型には2、4、8バイト整数と、4、8バイト浮動小数点および精度設定が可能な数があります。 表 8.2に使用可能な型を列挙します。

表8.2 数値データ型

型名格納サイズ説明範囲
smallint2バイト狭範囲の整数-32768から+32767
integer4バイト典型的に使用する整数-2147483648から+2147483647
bigint8バイト広範囲整数-9223372036854775808から+9223372036854775807
decimal可変長ユーザ指定精度、正確小数点より上は131072桁まで、小数点より下は16383桁まで
numeric可変長ユーザ指定精度、正確小数点より上は131072桁まで、小数点より下は16383桁まで
real4バイト可変精度、不正確6桁精度
double precision8バイト可変精度、不正確15桁精度
smallserial2バイト狭範囲自動整数1から32767
serial4バイト自動増分整数1から2147483647
bigserial8バイト広範囲自動増分整数1から9223372036854775807

数値データ型に対する定数の構文は4.1.2で説明しています。 数値データ型には対応する算術演算子と関数の一式が揃っています。 詳細は第9章を参照してください。 次節でデータ型について詳しく説明します。

8.1.1. 整数データ型 #

smallintintegerbigintは各種範囲の整数、つまり小数点以下の端数がない数を保持します。 許容範囲から外れた値を保存しようとするとエラーになります。

integer型は数値の範囲、格納サイズおよび性能において最も釣合いが取れていますので、一般的に使用されます。 smallint型は通常はディスク容量に制限が付いている場合にのみ使用します。 bigint型はintegerの許容範囲では十分ではない場合に使用されるよう設計されています。

SQLでは整数の型としてinteger(またはint)とsmallintbigintのみを規定しています。 int2int4およびint8は拡張ですが、いくつか他のSQLデータベースシステムでも使われています。

8.1.2. 任意の精度を持つ数 #

numeric型は、非常に大きな桁数で数値を格納できます。 通貨金額やその他正確性が求められる数量を保存する時は特に、この型を推奨します。 numericの値での計算は、可能なところ、例えば、足し算、引算、掛け算では、正確な結果(訳注:10進の小数で誤差が生じない、ということ)になります。 とは言っても、numericの値に対する計算は整数型、もしくは次節で説明する浮動小数点データ型に比較し非常に遅くなります。

この後の説明では、次の用語を使用します。 numeric精度(precision)とは数字全体の有効桁数です。 すなわち、小数点をはさんでいる両側の桁数の合計です。 numeric位取り(scale)とは、小数点の右側の小数部分の桁数をいいます。 そのため、23.5141という数値の精度は6で位取りは4となります。 整数の位取りは、ゼロであるとみなすことができます。

numeric列の数値の最大精度と最大位取りの両方を設定することができます。 numeric型の列を宣言するには次の構文を使います。

NUMERIC(precision, scale)

精度は正でなければならず、位取りは正または負であることができます(以下を参照)。 または、次のように指定します

NUMERIC(precision)

は位取りが0であることを選択します。 精度も位取りも指定せず、

NUMERIC

と記述すると、実装されている限界の精度まで、いかなる精度あるいは位取りの値も格納できる制約の無い数値列が作られます。 この類の列は入力値をいかなる特定の位取りにも変換しませんが、宣言された位取りを持つnumeric列は入力値をその位取りに変換します。 (標準SQLはデフォルトとして位取り0を要求していて、つまり、整数の精度に変換されます。 しかし、この方法はあまり役に立たないと思われます。 もし移植性を心配するなら、常に精度と位取りを明示的に設定してください。)

注記

明示的にnumeric型宣言で指定される場合の最大精度は1000です。 制約の無いnumeric列は表 8.2で説明する制限に従います。

格納される値の位取りが宣言された列の位取りより大きかった場合、システムは指定された小数部の桁まで値を丸めます。 そして、小数点の左側の桁数が、宣言された精度から宣言された位取りを差し引いた数を超える場合にエラーとなります。 例えば、

NUMERIC(3, 1)

として宣言された列は、値を小数第1位に丸め、-99.9から99.9までの値を格納できます。

PostgreSQL 15以降では、負の位取りを持つnumeric列を宣言することが許可されました。 その場合、値は小数点の左側に丸められます。 精度は、依然として丸められない最大桁数を表します。 したがって、

NUMERIC(2, -3)

として宣言された列は、千に近い値に丸められ、-99000から99000までの値を格納できます。 また、宣言された精度よりも大きな位取りを宣言することも許可されます。 このような列は小数値しか保持できず、小数点のすぐ右の0桁は、少なくとも宣言された位取りから宣言された精度を引いた値である必要があります。 例えば、

NUMERIC(3, 5)

として宣言された列は、小数点以下5桁に丸められ、-0.00999から0.00999までの値を格納できます。

注記

PostgreSQLでは、numeric型宣言の位取りを-1000~1000の範囲の任意の値にすることができます。 しかし、SQL標準では位取りを0~精度の範囲にする必要があります。 この範囲外の位取りを使用すると、他のデータベースシステムに移植できない可能性があります。

数値は物理的に先頭や末尾に0を付与されることなく格納されます。 したがって、列の宣言された精度と位取りは最大であり、固定的に割り当てられていません。 (この意味ではnumericchar(n)よりもvarchar(n)に似ています。) 実際の格納に必要な容量は、10進数4桁のそれぞれのグループに対して2バイトと、3から8バイトのオーバーヘッドです。

通常の数値に加え、numeric型はいくつかの特別な値を取ることができます。


Infinity
-Infinity
NaN

これらはIEEE 754標準から引用されたもので、それぞれ無限大マイナス無限大そして非数値を表します。 SQLコマンドの定数として記述する場合は、例えばUPDATE table SET x = '-Infinity'のように、引用符でくくらなければなりません。 入力の際、これらの文字列は大文字小文字の区別なく認識されます。 無限の値は代わりにinf-infと綴ることもできます。

無限の値は数学的に期待されたとおりに振る舞います。 例えば、Infinityに有限な値を加算した場合やInfinityInfinityを加算した場合はInfinityになります。しかし、InfinityからInfinityを減算した場合は、解釈が定まらないためNaN(数値では無い)になります。 無限大は制約が無いnumeric列にのみ格納できることに注意してください。これは理論上、いかなる有限な精度も超えているためです。

NaN(数値では無い)値は定義されていない計算の結果を表現するために使用されます。 通常、NaN入力を伴う操作は別のNaNを出力します。 その操作の入力がNaNを他の有限もしくは無限の数値型の値に置き換えられた場合に同じ出力が得られる時に限り例外があります。 この時はNaNの代わりにその操作の出力が使われます(この概念では例えば、NaNの0乗は1を出力します)。

注記

ほとんどの非数の概念の実装において、NaNは(NaNを含む)他の数値と等価にならないとみなされています。 numeric値をソートできる、また、ツリーを基にしたインデックスで使用できるように、PostgreSQLNaN同士は等しく、すべてのNaN以外の値よりも大きな値となるものとして扱います。

decimalnumeric型は等価です。 2つのデータ型はともに標準SQLに含まれます。

値を丸める際、numeric型は0から離れるように丸めますが、一方で(ほとんどのマシンでは)realdouble 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)

8.1.3. 浮動小数点データ型 #

realdouble precisionは不正確な(訳注:10進の小数で誤差が生じる、ということ)可変精度の数値データ型です。 現在サポートされている全てのプラットフォーム上では、これらのデータ型は、使用しているプロセッサ、オペレーティングシステムおよびコンパイラがサポートしていれば、通常は(それぞれ単精度および倍精度の)バイナリ浮動小数点演算用のIEEE規格754の実装です。

不正確というのは、ある値はそのままで内部形式に変換されずに近似値として保存されるということです。 ですから、保存しようとする値と抽出しようとする値の間に多少の差異が認められます。 これらのエラーを管理し計算によって補正をどうするかについては、数学とコンピュータ科学の系統すべてに関わることで、以下の点を除き触れません。

  • (金銭金額など)正確な記録と計算が必要な時は代わりにnumericを使用してください。

  • これらのデータ型で何か重要な件に対し複雑な計算を必要とする時、特に(無限大やアンダーフローのような)境界線におけるある種の振舞いについて信頼を置かなければならないのであれば、実装を注意深く検証しなければなりません。

  • 2つの浮動小数点値が等価であるのかどうかの比較は予想通りに行かない時もあります。

現在サポートされている全てのプラットフォームでは、real型は最低6桁の精度を持ち、1E-37から1E+37までの範囲です。 double precision型は最低15桁の精度でおよそ1E-307から1E+308までの範囲です。 大き過ぎたり小さ過ぎる値はエラーの原因になります。 入力値の精度が高過ぎる場合は丸められることがあります。 ゼロに限りなく近い値で、しかもゼロと異なる値として表現できない数値はアンダーフローエラーになります。

デフォルトでは、浮動小数の値は最も短い正確な10進数のテキスト形式で出力されます。 生成される10進値は、同じバイナリ精度で表現できる他の値よりも、実際に格納されているバイナリ値に近い値になります。 (ただし、出力値が2つの表現可能な値の厳密な中間になることはありません。これは、入力ルーチンが最も近い偶数に丸める規則を適切に考慮しないという広範囲にわたる不具合を避けるためです。) この値はfloat8型の値には最大17桁の10進数、float4型の値には最大9桁の10進数を使用します。

注記

この最も短く正確な出力フォーマットは従来の丸められた形式よりもはるかに速く値を生成します。

PostgreSQLの古いバージョンで生成された出力との互換性を確保し、出力精度を低くするために、代わりにextra_float_digitsパラメータを使用して丸めた10進数の出力を選択することができます。 値を0に設定した場合は、以前のデフォルト値である6(float4の場合)か15(float8の場合)の有効桁に丸めた値を戻します。 負の値を設定すると、桁数がさらに減少します。たとえば、-2を設定すると、出力はそれぞれ4桁または13桁に丸められます。

0より大きいextra_float_digitsの値は、最短の正確なフォーマットを選択します。

注記

精密な値を必要とするアプリケーションでは、従来、extra_float_digitsを3に設定して値を取得する必要がありました。 バージョン間の互換性を最大にするためには継続してそのように設定する必要があります。

通常の数値に加え、浮動小数点型では以下の特殊な値を取ります。


Infinity
-Infinity
NaN

これらはそれぞれ、IEEE 754の特殊な値、無限大負の無限大非数値を表します。 これらの値をSQLコマンドの定数として記述する場合、例えばUPDATE table SET x = '-Infinity'のように引用符でくくる必要があります。 入力の際、これらの文字列は大文字小文字の区別なく認識されます。 無限の値は代わりにinf-infと綴ることもできます。

注記

IEEE 754では、NaNは(NaNを含む)他のすべての浮動小数点値と比べた時に不等でなければならないと規定しています。 浮動小数点値をソートできる、また、ツリーを基にしたインデックスで使用できるように、PostgreSQLNaN同士は等しく、すべてのNaN以外の値よりも大きな値となるものとして扱います。

また、PostgreSQLでは不正確な数値型についての標準SQLの表記であるfloatfloat(p)をサポートしています。 ここで、p2進数桁数で最低限、許容可能な精度を指定します。 PostgreSQLfloat(1)からfloat(24)realを選択するものとして受け付け、float(25)からfloat(53)double precisionを選択するものとして受け付けます。 許容範囲外のpの値はエラーになります。 精度指定のないfloatdouble precisionとして解釈されます。

8.1.4. 連番型 #

注記

このセクションではPostgreSQL固有の自動増分列の作成方法について記述します。 SQL標準の識別列を作成する方法は、CREATE TABLEに記述されています。

smallserialserialおよびbigserialデータ型は正確にはデータ型ではなく、テーブルの列に一意の識別子を作成する簡便な表記法です (他のデータベースでサポートされるAUTO_INCREMENTプロパティに似ています)。 現在の実装では、

CREATE TABLE tablename (
    colname SERIAL
);

は以下を指定することと同じです。

CREATE SEQUENCE tablename_colname_seq AS integer;
CREATE TABLE tablename (
    colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;

このように整数列を作成し、その列のデフォルト値が連番ジェネレータから割り当てられるようにしました。 また、NOT NULL制約を適用することによって、NULL値が挿入されないようにします。 (たいていの場合は、重複する値を間違って挿入しないように、UNIQUE制約またはPRIMARY KEY制約も追加することになるでしょうが、これは自動的には行われません。) 最後に、シーケンスは列により所有されるものと印が付きます。 したがって、テーブルの列が削除された場合にシーケンスは削除されます。

注記

smallserialserialおよびbigserialはシーケンスを使って実装されているため、行の削除が行われていなくとも、列に"穴"や連番の抜けが発生するかもしれません。 また、テーブルへ正常に挿入されていないにも関わらず、シーケンスの値を"消費してしまう"こともあります。 これは、例えば挿入したトランザクションがロールバックされた時に発生することがあります。 詳細は9.17nextval()を参照してください。

serial列にシーケンスの次の値を挿入するには、serial列にそのデフォルト値を割り当てるよう指定してください。 これは、INSERT文の列リストからその列を除外する、もしくはDEFAULTキーワードを使用することで行うことができます。

serialserial4という型の名称は等価です。 ともにinteger列を作成します。 bigserialserial8という型の名称もbigint列を作成することを除いて同じ振舞いをします。 もしテーブルを使用する期間で231以上の識別子を使用すると予測される場合、bigserialを使用すべきです。 smallserialserial2という型の名称もまた、smallint列を作成することを除いて同じ振舞いをします。

serial列用に作成されたシーケンスは、それを所有する列が削除された時に自動的に削除されます。 列を削除せずにシーケンスを削除することができますが、これにより強制的に列のデフォルト式が削除されます。