数值类型包括 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
值的计算尽可能产生精确的结果,例如,加法、减法、乘法。但是,与整数类型或下一节中描述的浮点类型相比, numeric
值的计算非常慢。
我们在下面使用以下术语: numeric
的 精度 是整个数字中有效数字的总数,即小数点两侧的数字位数。 numeric
的 刻度 是小数部分中,即小数点右边的数字位数。因此,数字 23.5141 的精度为 6,刻度为 4。整数可以被认为具有 0 的刻度。
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(含)之间的值。还允许声明刻度大于声明的精度。这样的列只能保存小数值,并且要求小数点右侧的零数字位数至少为声明的刻度减去声明的精度。例如,一个声明为
NUMERIC(3, 5)
的列将把值舍入到小数点后 5 位,并且可以存储介于 -0.00999 和 0.00999(含)之间的值。
PostgreSQL 允许 numeric
类型声明中的刻度在 -1000 到 1000 的范围内。但是,该SQL标准要求刻度在 0 到 precision
范围内。使用超出该范围的刻度可能无法移植到其他数据库系统。
数值在物理上存储时没有任何额外的前导或尾随零。因此,列的声明精度和刻度是最大值,而不是固定分配。(从这个意义上说, numeric
类型更类似于 varchar(
而不是 n
)char(
。)实际存储要求是每组四位十进制数两个字节,再加上三到八字节的开销。n
)
除了普通的数值外, numeric
类型还具有几个特殊值
Infinity
-Infinity
NaN
这些值改编自 IEEE 754 标准,分别表示 “无穷大”、“负无穷大” 和 “非数字”。在 SQL 命令中将这些值写为常量时,必须用引号括起来,例如 UPDATE table SET x = '-Infinity'
。在输入时,这些字符串以不区分大小写的方式识别。无穷大值也可以拼写为 inf
和 -inf
。
无穷大值的行为符合数学期望。例如,Infinity
加任何有限值等于 Infinity
,Infinity
加 Infinity
也是如此;但是 Infinity
减去 Infinity
会产生 NaN
(非数字),因为它没有明确的解释。请注意,无穷大只能存储在无约束的 numeric
列中,因为它在概念上超过了任何有限精度限制。
NaN
(非数字)值用于表示未定义的计算结果。通常,任何包含 NaN
输入的操作都会产生另一个 NaN
。唯一的例外是,当操作的其他输入使得如果将 NaN
替换为任何有限或无限数值,就会获得相同的输出时;在这种情况下,将使用该输出值作为 NaN
。(此原则的一个示例是,NaN
乘以 0 的幂等于 1。)
在大多数实现 “非数字” 概念的系统中, NaN
不被认为等于任何其他数值(包括 NaN
)。为了允许 numeric
值进行排序并在基于树的索引中使用,PostgreSQL 将 NaN
值视为相等,并且大于所有非 NaN
值。
数据类型 decimal
和 numeric
是等效的。这两种类型都是SQL标准的一部分。
在对值进行舍入时,numeric
类型将舍入到远离零的方向,而(在大多数机器上)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
是不精确的、可变精度的数字类型。在所有当前支持的平台上,这些类型都是IEEE标准 754 中二进制浮点运算(分别为单精度和双精度)的实现,前提是底层处理器、操作系统和编译器支持它。
不精确意味着某些值无法精确转换为内部格式,并以近似值的形式存储,因此存储和检索值可能会显示细微差异。管理这些错误以及它们如何在计算中传播是整个数学和计算机科学分支的研究对象,此处将不再讨论,除了以下几点
如果您需要精确的存储和计算(例如货币金额),请使用 numeric
类型。
如果您想使用这些类型进行复杂的计算,尤其是对于重要的任何事项,特别是如果您依赖于边界情况下的某些行为(无穷大、下溢),则应仔细评估实现。
比较两个浮点数的相等性可能并不总是如预期的那样工作。
在所有当前支持的平台上,real
类型的范围约为 1E-37 到 1E+37,精度至少为 6 位小数。double precision
类型的范围约为 1E-307 到 1E+308,精度至少为 15 位。过大或过小的值会导致错误。如果输入数字的精度过高,可能会进行舍入。接近零且无法表示为与零不同的数字将导致下溢错误。
默认情况下,浮点数以文本形式以最短的精确十进制表示形式输出;生成的十进制值比相同二进制精度下可表示的任何其他值更接近于真实存储的二进制值。(但是,输出值目前绝不正好位于两个可表示值之间,以避免普遍存在的错误,即输入例程未正确遵守舍入到最接近的偶数规则。)此值最多使用 17 位有效十进制数字表示 float8
值,最多使用 9 位数字表示 float4
值。
这种最短的精确输出格式比传统的四舍五入格式快得多。
为了与旧版本的 PostgreSQL 生成的输出兼容,并允许降低输出精度,可以使用 extra_float_digits 参数选择舍入的十进制输出。将值设置为 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
)进行比较。为了允许对浮点数进行排序并在基于树的索引中使用,PostgreSQL 将 NaN
值视为相等,并且大于所有非 NaN
值。
PostgreSQL 还支持 SQL 标准符号 float
和 float(
来指定不精确的数字类型。此处,p
)p
指定了 二进制 位数的最小可接受精度。PostgreSQL 接受 float(1)
到 float(24)
选择 real
类型,而 float(25)
到 float(53)
选择 double precision
。p
的值超出允许范围会导致错误。float
未指定精度表示 double precision
。
本节介绍创建自增列的 PostgreSQL 特定方法。另一种方法是使用 SQL 标准标识列功能,如 第 5.3 节 所述。
数据类型 smallserial
、serial
和 bigserial
不是真正的类型,而只是创建唯一标识符列的符号便利(类似于某些其他数据库支持的 AUTO_INCREMENT
属性)。在当前实现中,指定
CREATE TABLEtablename
(colname
SERIAL );
等效于指定
CREATE SEQUENCEtablename
_colname
_seq AS integer; CREATE TABLEtablename
(colname
integer NOT NULL DEFAULT nextval('tablename
_colname
_seq') ); ALTER SEQUENCEtablename
_colname
_seq OWNED BYtablename
.colname
;
因此,我们创建了一个整数列,并安排从序列生成器为其分配默认值。应用了 NOT NULL
约束以确保无法插入空值。(在大多数情况下,您还希望附加一个 UNIQUE
或 PRIMARY KEY
约束以防止意外插入重复值,但这并非自动进行。)最后,序列被标记为“由” 该列拥有,因此,如果列或表被删除,则序列也将被删除。
由于 smallserial
、serial
和 bigserial
是使用序列实现的,因此即使从未删除任何行,列中出现的数值序列中也可能存在“空洞”或间隙。即使包含该值的行的插入从未成功,从序列分配的值仍然被“使用”。例如,这种情况可能发生在插入事务回滚的情况下。有关详细信息,请参阅 第 9.17 节 中的 nextval()
。
要将序列的下一个值插入 serial
列,请指定 serial
列应分配其默认值。可以通过在 INSERT
语句中从列列表中排除该列或使用 DEFAULT
关键字来实现。
类型名称 serial
和 serial4
是等效的:两者都创建 integer
列。类型名称 bigserial
和 serial8
的工作方式相同,只是它们创建一个 bigint
列。如果预计在表的生命周期内使用超过 231 个标识符,则应使用 bigserial
。类型名称 smallserial
和 serial2
的工作方式也相同,只是它们创建一个 smallint
列。
为 serial
列创建的序列在拥有该列的列被删除时会自动删除。您可以删除序列而不删除列,但这将强制删除列默认表达式。
如果您在文档中发现任何不正确的内容,与您对特定功能的体验不符或需要进一步澄清,请使用 此表格 报告文档问题。