数值类型包含两字节、四字节和八字节整数,四字节和八字节浮点数,以及可以选择精度的十进制数。 表 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
类型通常仅在磁盘空间不足时使用。当 integer
类型的范围不足时,设计使用 bigint
类型。
SQL仅指定以下整数类型:integer
(或 int
)、smallint
和 bigint
。类型名称 int2
、int4
和 int8
是扩展,其他一些SQL数据库系统也在使用。
类型 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(包括)之间存储值。
从 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
类型还有几个特殊值
无穷大
- 无穷大
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
乘方为零时会产生一。)
在大多数“非数字”概念的实现中,NaN
不被认为等于任何其他数字值(包括 NaN
)。为了让 numeric
值能够排序和用于基于树的索引,PostgreSQL 将 NaN
值视为相等且大于所有非 NaN
值。
类型 decimal
和 numeric
是等效的。这两种类型都是该标准的一部分。SQLstandard.
在舍入值时,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
类型在精度至少为 6 位小数的情况下,其范围在 1E-37 到 1E+37 之间。 double precision
类型的范围大约为 1E-307 到 1E+308,精度至少为 15 位数。太大或太小的值将引发错误。如果输入数字的精度过高,则可能会进行舍入。太接近于零、而无法代表为不为零的数字将会引发下溢错误。
默认情况下,浮点数值以其最短精确的小数表示形式输出为文本形式;产生的十进制值更接近真实存储的二进制值,而不是以相同二进制精度可表示的任何其他值。(但是,当前输出值永远不会恰好处于两个可表示值之间,以避免输入例程不恰当地遵守四舍五入原则的广泛错误。)对于 float8
值,此值最多将使用 17 位有效小数,而对于 float4
值来说,最多使用 9 位有效小数。
这种最短精度输出格式比历史舍入格式生成得更快。
为了与 PostgreSQL 旧版本生成的可输出值兼容,并允许降低输出精度,可使用 extra_float_digits 参数,选择舍入的十进制输出。设置值为 0 会恢复该值的旧默认舍入方式,即对于 float4
),舍入到 6 位有效小数,而对于 float8
) 来,舍入到 15 位有效小数。设置负值会进一步减少位数;例如,-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
)相等。为了允许对浮点值进行排序并在基于树的索引中使用,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
列创建的序列会被自动删除。您可以在不删除该列的情况下删除该序列,但这会强制删除列默认表达式。