PostgreSQL Data Types 数据类型实用教程
本教程介绍 PostgreSQL 常见内置类型与扩展类型。SQL 示例可按需在测试数据库中执行;创建类型的示例应先确认名称没有冲突。
数据类型速览
| 类别 | 常见类型 | 典型用途 |
|---|---|---|
| 数值(Numeric) | smallint、integer、bigint、numeric、real、double precision | 整数、精确小数、科学计算 |
| 字符(Character) | text、varchar、char | 文本与有长度限制的字符串 |
| 二进制(Binary) | bytea | 小型二进制内容 |
| 日期/时间(Date/Time) | date、time、timestamp、timestamptz、interval | 日期、时刻、时间点与时长 |
| 布尔(Boolean) | boolean | 真、假与未知 |
| 枚举(Enumerated) | 用户定义的 ENUM | 有限且相对稳定的取值集合 |
| 网络地址(Network address) | inet、cidr、macaddr | IP 地址、网段与 MAC 地址 |
| 位串(Bit string) | bit、bit varying | 位掩码与按位数据 |
| 全文搜索(Text Search) | tsvector、tsquery | 文档索引与搜索条件 |
| 标识符与结构化数据 | uuid、json、jsonb、数组、Range、Domain | 全局 ID、灵活结构、集合、范围与受约束类型 |
| 对象标识符(Object identifier) | oid、regclass 等 | 数据库系统目录对象引用 |
Numeric:数值类型
整数类型按范围选择;numeric 提供精确十进制计算;real 和 double precision 是近似浮点类型。
| 类型 | 说明 | 适用场景 |
|---|---|---|
smallint | 2 字节有符号整数 | 范围较小的计数或编码 |
integer / int | 4 字节有符号整数 | 常见整数量值 |
bigint | 8 字节有符号整数 | 较大计数与整数 ID |
numeric(p, s) / decimal | 精确十进制;p 为精度,s 为小数位数 | 金额、需要精确十进制的数 |
real / double precision | 近似浮点数,后者精度更高 | 科学计算、可接受近似误差的计算 |
CREATE TABLE measurements ( item_count integer NOT NULL, price numeric(12, 2) NOT NULL, ratio double precision );
SELECT 10 / 3;
-- 整数除法:3
SELECT 10::numeric / 3;
-- 精确十进制运算
金额通常用 numeric,避免二进制浮点近似误差。serial、bigserial 是历史上常用的自增列写法,不是独立的真正数据类型;新设计也可使用 identity 列。
Character:字符类型
text 和 varchar 在 PostgreSQL 中性能相近。只有确实需要限制最大字符数时才指定 varchar(n);char(n) 会按固定长度语义补空格。
CREATE TABLE profiles ( display_name varchar(80) NOT NULL, biography text, country_code char(2) );
SELECT 'hello'::text;
PostgreSQL 的字符长度按字符而非字节计算。char(n) 比较时尾随空格的处理容易令人意外,通常优先选 text 或 varchar。若要限制内容,应同时考虑空字符串、空格以及业务格式。
Binary Data:二进制数据
bytea 用于存储字节序列。PostgreSQL 常以十六进制格式显示二进制值;decode 和 encode 可在字节与文本表示之间转换。
CREATE TABLE attachments ( id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, content bytea NOT NULL );
-- 把十六进制文本转换为 bytea
SELECT decode('DEADBEEF', 'hex');
-- bytea 转为十六进制文本
SELECT encode(decode('DEADBEEF', 'hex'), 'hex');
大型文件通常更适合存储在对象存储或文件系统中,数据库只保存地址、校验值和元数据;是否使用 bytea 要结合备份、传输和访问模式决定。
Date/Time:日期与时间
| 类型 | 含义 | 提示 |
|---|---|---|
date | 日历日期 | 不包含时刻和时区 |
time / time with time zone | 一天中的时刻 | 带时区的 time 在业务中较少使用 |
timestamp | 不带时区的日期和时间字段 | 本身不代表唯一的全球时间点 |
timestamptz | 带时区语义的时间点 | 内部按时间点处理,输入和显示受时区设置影响 |
interval | 时间间隔 | 可表示月、日和时间部分 |
CREATE TABLE appointments ( appointment_date date NOT NULL, starts_at timestamptz NOT NULL, duration interval NOT NULL DEFAULT interval '30 minutes' );
SELECT date '2026-10-20';
SELECT timestamptz '2026-10-20 09:30:00+08';
SELECT now() + interval '1 day';
保存实际发生的时刻通常选 timestamptz;营业时间等纯本地钟表时间可选 time。采用 ISO 日期格式,并在应用中明确时区,避免依赖会话默认值。
Boolean:布尔类型
boolean 有 true、false 和 NULL(未知)三种逻辑状态。
CREATE TABLE feature_flags ( enabled boolean NOT NULL DEFAULT false );
SELECT true, false;
SELECT * FROM feature_flags WHERE enabled IS TRUE;
如果业务必须明确回答是或否,使用 NOT NULL;如果 NULL 表示“未知”或“尚未设置”,则需要在查询时显式处理三值逻辑。
Enumerated:枚举类型
枚举用于有限、相对稳定且有明确顺序的值集合。枚举标签区分大小写,排序顺序由创建类型时声明的顺序决定。
CREATE TYPE order_status AS ENUM ( 'pending', 'paid', 'shipped', 'cancelled' );
CREATE TABLE orders ( id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, status order_status NOT NULL DEFAULT 'pending' );
ALTER TYPE order_status ADD VALUE 'refunded';
枚举值不适合频繁变化或由用户动态管理的类别。可以添加新值,但移除或重排已有值通常需要迁移并重建类型;可变分类常用独立字典表和外键表达。