支持的版本: 当前 (17) / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2

8.1. 数值类型 #

数值类型包括两字节、四字节和八字节的整数,四字节和八字节的浮点数,以及可选择精度的十进制数。表 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 章。以下章节将详细描述这些类型。

8.1.1. 整数类型 #

smallintintegerbigint 类型存储整数,即没有小数部分的数字,范围各不相同。尝试存储超出允许范围的值将导致错误。

integer 类型是常见的选择,因为它在范围、存储大小和性能之间提供了最佳平衡。smallint 类型通常仅在磁盘空间有限时使用。bigint 类型旨在用于 integer 类型的范围不足时。

SQL仅指定整数类型 integer(或 int)、smallintbigint。类型名称 int2int4int8 是扩展,其他一些SQL数据库系统也使用这些扩展。

8.1.2. 任意精度数字 #

numeric 类型可以存储具有大量位数的数字。特别推荐用于存储货币金额和其他需要精确性的数量。numeric 值的计算在可能的情况下产生精确的结果,例如,加法、减法、乘法。但是,与整数类型或下一节中描述的浮点类型相比,numeric 值的计算速度非常慢。

我们在下面使用以下术语:numeric精度是整个数字中有效数字的总数,即小数点两侧的位数。 numeric标度是小数部分中小数位数的计数,即小数点右侧的位数。因此,数字 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 之间的值(包括 -99.9 和 99.9)。

PostgreSQL 15 开始,允许使用负标度声明 numeric 列。然后,值将四舍五入到小数点左侧。精度仍然表示未四舍五入的最大位数。因此,声明为

NUMERIC(2, -3)

的列将值四舍五入到最接近的千位,并且可以存储 -99000 到 99000 之间的值(包括 -99000 和 99000)。还允许声明大于声明精度的标度。这样的列只能容纳小数值,并且它要求小数点右侧的零位数至少为声明的标度减去声明的精度。例如,声明为

NUMERIC(3, 5)

的列会将值四舍五入到 5 位小数,并且可以存储 -0.00999 到 0.00999 之间的值(包括 -0.00999 和 0.00999)。

注意

PostgreSQL 允许 numeric 类型声明中的标度为 -1000 到 1000 范围内的任何值。但是,SQL标准要求标度在 0 到 精度 的范围内。使用该范围之外的标度可能不适用于其他数据库系统。

数值在物理上存储时没有任何额外的开头或结尾的零。因此,列声明的精度和标度是最大值,而不是固定分配。(从这个意义上说,numeric 类型更类似于 varchar(n),而不是 char(n)。)实际存储要求是每四位十进制数字占用两个字节,外加三到八字节的开销。

除了普通的数值外,numeric 类型还有几个特殊值


无穷大
-无穷大
NaN

这些值改编自 IEEE 754 标准,分别表示无穷大负无穷大非数字。在 SQL 命令中将这些值写为常量时,必须将它们用引号引起来,例如 UPDATE table SET x = '-Infinity'。在输入时,这些字符串以不区分大小写的方式识别。无穷大值也可以拼写为 inf-inf

无穷大值的行为符合数学预期。例如,Infinity 加上任何有限值都等于 InfinityInfinity 加上 Infinity 也是如此;但是 Infinity 减去 Infinity 会产生 NaN(非数字),因为它没有明确的解释。请注意,无穷大只能存储在无约束的 numeric 列中,因为它在概念上超过了任何有限的精度限制。

NaN(非数字)值用于表示未定义的计算结果。一般来说,任何带有 NaN 输入的操作都会产生另一个 NaN。唯一的例外是当操作的其他输入是这样的,如果将 NaN 替换为任何有限或无限的数值,也会获得相同的输出;然后,该输出值也用于 NaN。(该原则的一个例子是,NaN 的零次幂产生 1。)

注意

在大多数非数字概念的实现中,NaN 不被认为等于任何其他数值(包括 NaN)。为了允许对 numeric 值进行排序并在基于树的索引中使用,PostgreSQLNaN 值视为相等,并且大于所有非 NaN 值。

类型 decimalnumeric 是等效的。这两种类型都是SQL标准的一部分。

在舍入数值时,numeric 类型会将中间值舍入远离零,而(在大多数机器上)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 数据类型是不精确的、可变精度的数值类型。在所有当前支持的平台上,这些类型都是以下标准的实现:IEEE二进制浮点运算标准 754(分别为单精度和双精度),在底层处理器、操作系统和编译器支持的范围内。

不精确意味着某些值无法精确转换为内部格式,而是存储为近似值,因此存储和检索值可能会出现细微的差异。管理这些错误以及它们如何在计算中传播是数学和计算机科学的一个分支的主题,这里不会讨论,除了以下几点:

  • 如果您需要精确的存储和计算(例如用于货币金额),请使用 numeric 类型。

  • 如果您想使用这些类型进行重要的复杂计算,特别是当您依赖边界情况(无穷大、下溢)的特定行为时,您应该仔细评估实现。

  • 比较两个浮点值的相等性可能并不总是按预期工作。

在所有当前支持的平台上,real 类型的范围约为 1E-37 到 1E+37,精度至少为 6 位十进制数字。double precision 类型的范围约为 1E-307 到 1E+308,精度至少为 15 位数字。太大或太小的值会导致错误。如果输入数字的精度太高,可能会发生舍入。太接近零且无法与零区分的数字将导致下溢错误。

默认情况下,浮点值以文本形式输出,使用其最短的精确十进制表示形式;生成的十进制值比同一二进制精度中可表示的任何其他值更接近真实存储的二进制值。(但是,为了避免输入例程不正确地遵守舍入到最近偶数的规则而导致的广泛错误,输出值目前永远不是两个可表示值之间的精确中间值。)对于 float8 值,此值最多使用 17 个有效十进制数字,对于 float4 值,最多使用 9 个有效数字。

注意

这种最短精确输出格式比历史上的舍入格式生成速度快得多。

为了与旧版本 PostgreSQL 生成的输出兼容,并允许降低输出精度,可以使用 extra_float_digits 参数来选择舍入的十进制输出。将值设置为 0 会恢复之前的默认值,即将值舍入到 6 位(对于 float4)或 15 位(对于 float8)有效十进制数字。设置负值会进一步减少位数;例如,-2 将分别将输出舍入到 4 或 13 位数字。

任何大于 0 的 extra_float_digits 值都会选择最短精确格式。

注意

历史上,想要精确值的应用程序必须将 extra_float_digits 设置为 3 才能获得它们。为了在版本之间获得最大的兼容性,它们应该继续这样做。

除了普通的数值之外,浮点类型还有几个特殊值:


无穷大
-无穷大
NaN

这些值分别表示 IEEE 754 特殊值 无穷大负无穷大非数字。当在 SQL 命令中将这些值写为常量时,您必须用引号将它们括起来,例如 UPDATE table SET x = '-Infinity'。在输入时,这些字符串以不区分大小写的方式识别。无穷大值也可以拼写为 inf-inf

注意

IEEE 754 规定 NaN 不应与任何其他浮点值(包括 NaN)进行比较。为了允许对浮点值进行排序并在基于树的索引中使用,PostgreSQLNaN 值视为相等,并且大于所有非 NaN 值。

PostgreSQL 还支持 SQL 标准符号 floatfloat(p) 来指定不精确的数值类型。在这里,p 指定以二进制数字表示的最小可接受精度。PostgreSQL 接受 float(1)float(24) 作为选择 real 类型,而 float(25)float(53) 选择 double precisionp 的值超出允许范围会引发错误。未指定精度的 float 被视为表示 double precision

8.1.4. 自增类型 #

注意

本节描述了 PostgreSQL 特有的创建自增列的方式。另一种方法是使用 SQL 标准的标识列功能,详见 第 5.3 节

smallserialserialbigserial 数据类型不是真正的类型,而仅仅是创建唯一标识符列的表示法便利(类似于某些其他数据库支持的 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 约束用于确保无法插入空值。(在大多数情况下,您还需要附加 UNIQUEPRIMARY KEY 约束,以防止意外插入重复值,但这并不是自动的。)最后,该序列被标记为该列拥有,以便在删除该列或表时将其删除。

注意

由于 smallserialserialbigserial 是使用序列实现的,因此列中出现的值序列中可能存在“空洞”或间隙,即使从未删除任何行。从序列分配的值仍然会被“用完”,即使包含该值的行从未成功插入到表列中。例如,如果插入事务回滚,则可能会发生这种情况。有关详细信息,请参阅 第 9.17 节中的 nextval()

要将序列的下一个值插入到 serial 列中,请指定应为 serial 列分配其默认值。可以通过从 INSERT 语句中的列列表中排除该列,或者通过使用 DEFAULT 关键字来完成此操作。

类型名称 serialserial4 是等效的:两者都创建 integer 列。类型名称 bigserialserial8 的工作方式相同,只是它们创建 bigint 列。如果您预计在表的生命周期内使用超过 231 个标识符,则应使用 bigserial。类型名称 smallserialserial2 的工作方式也相同,只是它们创建 smallint 列。

serial 列创建的序列会在删除所属列时自动删除。您可以删除该序列而不删除该列,但这将强制删除列的默认表达式。

提交更正

如果您发现文档中的任何内容不正确、与您使用特定功能的经验不符或需要进一步澄清,请使用此表单报告文档问题。