第 3 章 数据类型
目录
PostgreSQL 提供了丰富的原生数据类型。用户可以使用CREATE TYPE命令向
PostgreSQL添加新类型。
表 3.1列出了标准发行版中包含的所有通用数据类型。“别名”列中列出的大多数替代名称,是 PostgreSQL 出于历史原因在内部使用的名称。此外还有一些内部使用或已废弃的类型可用,但这里没有列出。
表 3.1. 数据类型
| 类型名 | 别名 | 描述 |
|---|---|---|
bigint | int8 | 有符号的8字节整数 |
bigserial | serial8 | 自动递增的8字节整数 |
bit | 定长位串 | |
bit varying( | varbit( | 变长位串 |
boolean | bool | 逻辑布尔值(真/假) |
box | 二维平面上的矩形框 | |
bytea | 二进制数据 | |
character( | char( | 定长字符串 |
character varying( | varchar( | 变长字符串 |
cidr | IP 网络地址 | |
circle | 二维平面上的圆 | |
date | 日历日期(年、月、日) | |
double precision | float8 | 双精度浮点数 |
inet | IP 主机地址 | |
integer | int, int4 | 有符号4字节整数 |
interval( | 通用时间段 | |
line | 二维平面上的无限直线 | |
lseg | 二维平面上的线段 | |
macaddr | MAC 地址 | |
money | 美式货币 | |
numeric [ ( | decimal [ ( | 精度可选择的精确数值 |
oid | 对象标识符 | |
path | 二维平面上的开放和闭合几何路径 | |
point | 二维平面上的几何点 | |
polygon | 二维平面上的封闭几何路径 | |
real | float4 | 单精度浮点数 |
smallint | int2 | 有符号2字节整数 |
serial | serial4 | 自动递增的4字节整数 |
text | 变长字符串 | |
time [ ( | 一天中的时间 | |
time [ ( | timetz | 一天中的时间,包括时区 |
timestamp [ ( | timestamp | 日期和时间 |
timestamp [ ( | timestamptz | 日期和时间,包括时区 |
兼容性
SQL 指定了下列类型(或其拼写):bit、bit varying、boolean、char、character、character
varying、varchar、date、double precision、integer、interval、numeric、decimal、real、smallint、time、timestamp(带或不带时区)。
每种数据类型都有由其输入和输出函数决定的外部表示。许多内建类型都有显而易见的外部格式。但也有一些类型要么为 PostgreSQL 所独有(例如开放和闭合路径),要么有多种可选格式(例如日期和时间类型)。大多数对应于基本类型(如整数和浮点数)的输入和输出函数会做一些错误检查。有些输入和输出函数是不可逆的。也就是说,输出函数的结果与原始输入相比可能损失精度。
为了提高执行速度,某些运算符和函数(例如加法和乘法)不做运行时错误检查。例如在某些系统上,某些数据类型的数值运算符可能静默下溢或上溢。
3.1. 数字类型 #
数值类型包括二字节、四字节和八字节整数,四字节和八字节浮点数,以及固定精度的小数。
表 3.2. 数字类型
| 类型名 | 存储尺寸 | 描述 | 范围 |
|---|---|---|---|
smallint | 2字节 | 定点数 | -32768 到 +32767 |
integer | 4字节 | 定点数的常用选择 | -2147483648 到 +2147483647 |
bigint | 8字节 | 极大范围定点数 | -9223372036854775808 到 9223372036854775807 |
decimal | 可变 | 用户指定精度,精确 | 无限制 |
numeric | 可变 | 用户指定精度,精确 | 无限制 |
real | 4字节 | 可变精度,不精确 | 6位十进制精度 |
double precision | 8字节 | 可变精度,不精确 | 15位十进制精度 |
serial | 4字节 | 自动递增的整数 | 1到2147483647 |
bigserial | 8字节 | 自动递增的整数 | 1到9223372036854775807 |
数字类型常量的语法在第 1.1.2 节里描述。数字类型有一整套对应的算术操作符和函数。相关信息请参考第 4 章。下面的几节详细描述这些类型。
3.1.1. 整数类型 #
smallint、integer 和
bigint 类型存储整数,即不带小数部分的数,取值范围各异。试图存储超出允许范围的值将导致错误。
常用的类型是integer,因为它提供了在范围、存储空间和性能之间的最佳平衡。一般只有在磁盘空间紧张的时候才使用smallint类型。而bigint类型只有在integer的范围不够用时才应使用,因为后者(integer)无疑更快。
bigint类型并非在所有平台上都能正确工作,因为它依赖于编译器对八字节整数的支持。在没有这种支持的机器上,bigint的行为与integer相同(但仍占用八个字节的存储空间)。不过,我们不知道有任何合理的平台属于这种情况。
SQL 只规定了整数类型
integer(或
int)和
smallint。类型
bigint 以及类型名
int2、int4 和
int8 都是扩展,它们也被其他各种
RDBMS 产品共用。
注意
如果你有一个带索引的 smallint 或
bigint 类型的列,可能会遇到系统不使用该索引的问题。例如,如下形式的子句
... WHERE smallint_column = 42
不会使用索引,因为系统把类型
integer 指派给常量
42,而 PostgreSQL
目前在涉及两种不同数据类型时无法使用索引。一个变通办法是给常量加单引号,即:
... WHERE smallint_column = '42'
这会使系统推迟类型解析,从而为常量指派正确的类型。
3.1.2. 任意精度数字 #
numeric
类型可以存储大小和精度几乎不受限制的数字,同时能精确存储所有数字并精确执行全部计算。特别推荐用它存储货币金额和其他要求精确的数量。但与下一节描述的浮点类型相比,numeric
类型非常慢。
下面使用如下术语:numeric的小数位数是小数部分中十进制数字的数量,即小数点右侧的位数。numeric的精度是整个数中有效数字的总数,即小数点两侧的数字位数之和。因此,数值 23.5141 的精度为 6,小数位数为 4。整数可以视为小数位数为零。
numeric
类型的精度和小数位数都可以配置。要声明一个
numeric 类型的列,可使用如下语法
NUMERIC(precision,scale)
精度必须为正,小数位数为零或正。也可以
NUMERIC(precision)选择小数位数 0。指定
NUMERIC
而不带任何精度和小数位数,则会创建一个可以存储任意精度和小数位数的数值的列,精度上限为实现限制。这种列不会把输入值强制转换为任何特定的小数位数,而声明了小数位数的
numeric
列会把输入值强制转换为该小数位数。(SQL
标准要求默认小数位数为
0,即强制转换为整数精度。我们觉得这没什么用处。如果你关心可移植性,就总是显式指定精度和小数位数。)
如果一个值的精度或小数位数大于列所声明的精度或小数位数,系统会尝试对该值四舍五入。如果无法通过四舍五入满足声明的限制,则会引发一个错误。
decimal 和
numeric 类型是等效的。两种类型都是
SQL 标准的一部分。
3.1.3. 浮点类型 #
real 和
double
precision 数据类型是不精确的可变精度数值类型。实践中,在底层处理器、操作系统和编译器支持的范围内,这些类型通常实现为
IEEE 754
二进制浮点(分别为单精度和双精度)。
所谓不精确,是指某些值无法被精确转换为内部格式,只能以近似值存储,因此存储并再取出一个值时,可能会看到轻微差异。如何处理这类误差以及它们在计算中如何传播,是数学和计算机科学中的一个独立领域,这里不再展开,只强调以下几点:
如果你要求准确的存储和计算(例如计算货币金额),应使用
numeric类型。如果你想用这些类型进行任何重要的复杂计算,尤其是依赖边界情形(无穷大、下溢)特定行为的计算,那么应该仔细评估其实现。
比较两个浮点值是否相等,未必总能得到符合预期的结果。
通常,real
类型的取值范围至少是
-1E+37 到 +1E+37,精度至少为
6 位十进制数字。double
precision 类型通常的取值范围约为
-1E+308 到 +1E+308,精度至少
15 位。太大或太小的值会导致错误。输入数字精度过高时可能发生四舍五入。与零太接近而无法与零区分的数字会导致下溢错误。
3.1.4. serial 类型 #
serial
数据类型并不是真正的类型,而只是为在表中设置唯一标识符列提供的一种记法上的便利。在当前的实现中,指定
CREATE TABLEtablename(colnameSERIAL );
等效于指定:
CREATE SEQUENCEtablename_colname_seq; CREATE TABLEtablename(colnameinteger DEFAULT nextval('tablename_colname_seq') UNIQUE NOT NULL );
这样,我们创建了一个整数列,并安排其默认值由一个序列生成器指派。同时应用了 UNIQUE 和 NOT NULL 约束,以确保显式插入的值也永远不会重复。
类型名 serial 和
serial4 等效:两者都创建
integer 列。类型名
bigserial 和
serial8 的作用方式相同,只是它们创建
bigint
列。如果你预计在表的整个生命周期中会使用超过
231
个标识符,就应使用
bigserial。
支撑 serial
类型的隐式序列不会在包含
serial 类型的表被删除时自动删除。因此,按顺序执行下面的命令很可能会失败:
CREATE TABLEtablename(colnameSERIAL); DROP TABLEtablename; CREATE TABLEtablename(colnameSERIAL);
该序列会一直留在数据库中,直到用
DROP SEQUENCE 显式删除。(这一烦扰在将来的某个版本中可能会被改变。)