↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 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.0 / 7.4 / 7.3 / 7.2 / 7.1 / 7.0 / 6.5 / 6.4
历史版本。 PostgreSQL 9.3 已结束支持。 2018-11-08. 请参阅 当前版本手册.

第 8 章 数据类型

PostgreSQL 提供了丰富的原生数据类型。用户可以使用CREATE TYPE命令向 PostgreSQL添加新类型。

表 8.1展示了所有内置的通用数据类型。“别名”列中列出的多数可选名称,都是 PostgreSQL出于历史原因在内部使用的名称。此外,还有一些内部使用或已废弃的类型也可用,但未在此列出。

表 8.1. 数据类型

名字别名描述
bigintint8有符号的8字节整数
bigserialserial8自动递增的8字节整数
bit [ (n) ] 定长位串
bit varying [ (n) ]varbit [ (n) ]变长位串
booleanbool逻辑布尔值(真/假)
box 平面上的矩形框
bytea 二进制数据(“字节数组”)
character [ (n) ]char [ (n) ]定长字符串
character varying [ (n) ]varchar [ (n) ]变长字符串
cidr IPv4或IPv6网络地址
circle 平面上的圆
date 日历日期(年、月、日)
double precisionfloat8双精度浮点数(8 字节)
inet IPv4或IPv6主机地址
integerint, int4有符号4字节整数
interval [ fields ] [ (p) ] 时间段
json 文本 JSON 数据
line 平面上的无限长的线
lseg 平面上的线段
macaddr MAC(Media Access Control)地址
money 货币数量
numeric [ (p, s) ]decimal [ (p, s) ]可选择精度的精确数字
path 平面上的几何路径
point 平面上的几何点
polygon 平面上的封闭几何路径
realfloat4单精度浮点数(4字节)
smallintint2有符号2字节整数
smallserialserial2自动递增的2字节整数
serialserial4自动递增的4字节整数
text 变长字符串
time [ (p) ] [ without time zone ] 一天中的时间(无时区)
time [ (p) ] with time zonetimetz一天中的时间,包括时区
timestamp [ (p) ] [ without time zone ] 日期和时间(无时区)
timestamp [ (p) ] with time zonetimestamptz日期和时间,包括时区
tsquery 文本搜索查询
tsvector 文本搜索文档
txid_snapshot 用户级事务 ID 快照
uuid 通用唯一标识符
xml XML 数据

兼容性

下列类型(或它们的这些拼写形式)由SQL规定:bigint、bit、bit varying、boolean、char、character varying、character、varchar、date、double precision、integer、interval、numeric、decimal、real、smallint、time(有时区或无时区)、timestamp(有时区或无时区)、xml。

每种数据类型都有一种由其输入和输出函数决定的外部表示。许多内置类型的外部格式都很直观。不过,也有一些类型是 PostgreSQL所特有的,例如几何路径;还有一些类型可能存在多种可能的格式,例如日期/时间类型。有些输入和输出函数并不可逆,也就是说,输出函数的结果与原始输入相比可能会丢失精度。

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. 整数类型 #

类型 smallint、integer 和 bigint 用于存储不同范围的整数,也就是没有小数部分的数。试图存储超出允许范围的值会导致错误。

常用的类型是integer,因为它提供了在范围、存储空间和性能之间的最佳平衡。一般只有在磁盘空间紧张的时候才使用 smallint类型。bigint则设计用于integer的范围不够的情况。

SQL只规定了整数类型integer(或int)、smallint和bigint。类型int2、int4和int8都是扩展,也在某些其他SQL数据库系统中使用。

8.1.2. 任意精度数值 #

类型numeric可以存储非常多位的数字并精确地执行计算。我们特别建议将它用于货币金额和其它要求精确的数量。不过,numeric类型上的算术运算比整数类型或者下一节描述的浮点数类型要慢很多。

下面使用如下术语:numeric的精度是整个数中有效数字的总数,即小数点两侧的数字位数之和。numeric的小数位数是小数部分中十进制数字的数量,即小数点右侧的位数。因此,数值 23.5141 的精度为 6,小数位数为 4。整数可以视为小数位数为零。

可以配置numeric列的最大精度和最大小数位数。要声明numeric类型的列,使用以下语法:

NUMERIC(precision, scale)

精度必须为正数,小数位数必须为零或正数。也可以使用:

NUMERIC(precision)

这会选择小数位数为 0。指定:

NUMERIC

而不指定任何精度或小数位数,会创建一个可存储任意精度和小数位数数值的列,直到达到实现对精度的限制。这种列不会把输入值强制转换为某个特定的小数位数,而声明了小数位数的numeric列会将输入值强制转换为该小数位数。(SQL标准要求默认小数位数为 0,即强制转换为整数精度。我们认为这没有多少用处。如果你关心可移植性,请始终显式指定精度和小数位数。)

注意

在类型声明中显式指定精度时,所允许的最大值为 1000;未指定精度的NUMERIC受表 8.2中所述限制的约束。

如果要存储的值的小数位数大于该列声明的小数位数,系统会把该值舍入到指定的小数位数。然后,如果小数点左侧的位数超过了声明的精度减去声明的小数位数,就会报错。

数值在物理上存储时不会保留多余的前导零或尾随零。因此,列上声明的精度和小数位数只是最大值,而不是固定分配的空间(从这个意义上说,numeric更像 varchar(n),而不像 char(n))。实际存储需求是每四个十进制数字组占两个字节,再加上 3 到 8 字节的开销。

除了普通数值外,numeric类型还允许特殊值NaN,表示“非数”。对NaN的任何运算都会产生另一个NaN。在 SQL 命令中将该值写为常量时,必须加上引号,例如UPDATE table SET x = 'NaN'。输入时,字符串NaN的识别不区分大小写。

注意

在大多数“非数字”概念的实现中,NaN 都被认为不等于任何其他数值(包括 NaN 本身)。为了让 numeric 值能够排序并用于基于树的索引,PostgreSQL 将 NaN 值视为彼此相等,并且大于所有非 NaN 值。

类型decimal和numeric是等效的。两种类型都是SQL标准的一部分。

8.1.3. 浮点类型 #

数据类型real和double precision是不精确的、变精度的数字类型。实际上,在底层处理器、操作系统和编译器支持的范围内,这两种类型通常实现了IEEE 754 二进制浮点算术标准(分别对应单精度和双精度)。

所谓不精确,是指某些值无法被精确转换为内部格式,只能以近似值存储,因此存储并再取出一个值时,可能会看到轻微差异。如何处理这类误差以及它们在计算中如何传播,是数学和计算机科学中的一个独立领域,这里不再展开,只强调以下几点:

  • 如果你要求准确的存储和计算(例如计算货币金额),应使用numeric类型。

  • 如果你想用这些类型进行任何重要的复杂计算,尤其是依赖边界情形(无穷大、下溢)特定行为的计算,那么应该仔细评估其实现。

  • 比较两个浮点值是否相等,未必总能得到符合预期的结果。

在大多数平台上,real类型的范围至少为 1E-37 到 1E+37,精度至少为 6 位十进制数字。double precision类型的范围通常约为 1E-307 到 1E+308,精度至少为 15 位数字。过大或过小的值会导致错误。如果输入数字的精度过高,可能会发生舍入。过于接近零且无法表示为与零不同的数值,会导致下溢错误。

注意

extra_float_digits设置控制浮点值转换为文本输出时所包含的额外有效数字位数。使用默认值0时,输出在 PostgreSQL 支持的每个平台上都相同。增大该值会使输出更精确地表示所存储的值,但可能不具有可移植性。

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

Infinity
-Infinity
NaN

它们分别表示 IEEE 754 的特殊值“无穷大”,“负无穷大”和“非数字”。(在浮点运算不遵循 IEEE 754 的机器上,这些值可能无法按预期工作。)在 SQL 命令中将这些值写为常量时,必须加上引号,例如UPDATE table SET x = 'Infinity'。输入时,这些字符串的识别不区分大小写。

注意

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 7.4 之前,float(p)中的精度被理解为这么多位十进制数字。这一点已被修正,以符合 SQL 标准,即精度以二进制位来度量。假定real和double precision的尾数分别恰好有 24 位和 53 位,对于 IEEE 标准浮点实现而言是正确的。在非 IEEE 平台上可能会有少许偏差,但为简单起见,所有平台都使用相同的p取值范围。

8.1.4. serial 类型 #

smallserial、serial 和 bigserial 并不是真正的数据类型,它们只是为了创建唯一标识符列而提供的记法便利(类似于其他一些数据库支持的 AUTO_INCREMENT 属性)。在当前实现中,下列语句:

CREATE TABLE tablename (
    colname SERIAL
);

等价于以下语句:

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

这样就创建了一个整数列,并把它的默认值设置为从序列生成器中取值。同时还会加上NOT NULL约束,以确保不能插入空值。(在大多数情况下,你可能还会希望再加上UNIQUE 或PRIMARY KEY约束,以防意外插入重复值,但这不会自动发生。)最后,该序列会被标记为“属于”该列,这样当列或表被删除时,序列也会随之删除。

注意

因为 smallserial、serial 和 bigserial 是用序列实现的,所以即使没有删除任何行,列中出现的值序列也可能存在"空洞"或缺口。即使包含该值的行从未成功插入表中,从序列分配出去的值仍会被视为"已使用"。例如,如果插入事务回滚,就会发生这种情况。详细信息见第 9.16 节中的 nextval()。

要向 serial 列插入序列中的下一个值,应指定让serial列使用其默认值。这既可以通过在 INSERT 语句的列表中省略该列来实现,也可以通过使用 DEFAULT 关键字来实现。

类型名 serial 和 serial4 是等价的:二者都会创建 integer 列。类型名 bigserial 和 serial8 的工作方式相同,只是它们创建的是 bigint 列。如果预计表在其生命周期内会使用超过 231 个标识符,就应使用 bigserial。类型名 smallserial 和 serial2 也同理,只是它们创建的是 smallint 列。

为 serial 列创建的序列会在其所属列被删除时自动删除。你也可以在不删除该列的情况下删除该序列,但这会强制移除该列的默认值表达式。

注意

在PostgreSQL 7.3 之前,serial 隐含 UNIQUE。现在这不再是自动的了。如果希望一个 serial 列拥有唯一约束或作为主键,现在必须像其他数据类型一样显式指定。

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.