2025年9月25日: PostgreSQL 18 发布!
支持的版本: 当前 (18) / 17 / 16 / 15 / 14 / 13
开发版本: 开发版
不支持的版本: 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”列,其中可以存储任何长度的数值,直到实现限制。这种列不会将输入值强制转换为任何特定标度,而声明了标度的 numeric 列会将输入值强制转换为该标度。( numericSQL标准要求默认标度为 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 的范围内。但是,SQLSQL 标准要求标度在 0 到 精度 的范围内。使用超出该范围的标度可能无法移植到其他数据库系统。

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

除了普通数值外, numeric 类型还包含一些特殊值


无穷大
-无穷大
NaN

这些值取自 IEEE 754 标准,分别代表“无穷大”、“负无穷大”和“非数字”。在 SQL 命令中将这些值写为常量时,必须用引号括起来,例如 UPDATE table SET x = '-Infinity'。输入时,这些字符串不区分大小写。无穷大值还可以拼写为 inf-inf

无穷大值按照数学预期进行运算。例如, Infinity 加上任何有限值等于 InfinityInfinity 加上 Infinity 也等于 Infinity;但是 Infinity 减去 Infinity 会得到 NaN(非数字),因为它没有明确定义的解释。请注意,无穷大只能存储在无约束的 numeric 列中,因为它名义上超过了任何有限的精度限制。

NaN(非数字)值用于表示未定义的计算结果。通常,任何带有 NaN 输入的操作都会产生另一个 NaN。唯一的例外是当操作的其他输入使得如果将 NaN 替换为任何有限或无限数值,都会得到相同的输出时;在这种情况下,该输出值也将用于 NaN。(这个原则的一个例子是 NaN 的零次幂得到 1。)

注意

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

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

在四舍五入值时, numeric 类型将中间值(例如 1.5)四舍五入为远离零的值,而(在大多数机器上) 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 是不精确的、可变精度的数值类型。在所有当前支持的平台上,这些类型都是IEEE754 二进制浮点运算标准(单精度和双精度)的实现,只要底层处理器、操作系统和编译器支持。这意味着将某些值转换为内部格式时可能无法精确转换,而是存储为近似值,因此存储和检索值时可能会显示轻微的差异。

不精确意味着某些值无法精确转换为内部格式并存储为近似值,因此存储和检索值时可能会显示轻微的差异。管理这些错误以及它们如何传播到计算中是整个数学和计算机科学分支的主题,此处不作讨论,但以下几点除外:

  • 如果您需要精确的存储和计算(例如用于货币金额),请使用 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 列创建的序列在拥有它的列被删除时会自动删除。您可以删除序列而不删除列,但这将强制删除列的默认表达式。

提交更正

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