创建时间: 2026-09-01最后更新: 2026-09-01

1. 类型

数据库中的每一列都必须声明类型。类型告诉 PostgreSQL 这一列允许保存什么数据、怎样比较、怎样排序,以及可以执行哪些运算。

例如,任务标题适合使用文本,优先级适合使用整数,截止时间适合使用带时区的时间:

type-example.sql
1
CREATE TABLE task_type_example (
2
title text,
3
priority smallint,
4
completed boolean,
5
due_at timestamptz
6
);

Python 也有 str、int、bool 等类型,但 Python 类型和数据库类型并不是同一个系统。Python 对象需要经过数据库驱动转换,才能成为 PostgreSQL 能保存的值:

PythonPostgreSQL说明
strtext、varchar标题、描述等字符串
intsmallint、integer、bigint、numeric实际列类型决定最终可接受的范围
floatdouble precision近似浮点数
Decimalnumeric金额等精确小数
boolbooleanTrue 和 False
datedate只包含日期
不带 tzinfo 的 datetimetimestamp不表示确定的全球时间点
带 tzinfo 的 datetimetimestamptz表示确定的时间点
timedeltainterval时间间隔
UUIDuuidUUID 标识符
bytes、bytearray、memoryviewbytea二进制数据
listPostgreSQL 数组Psycopg 默认把同类型列表适配为数组
使用 Json、Jsonb 包装的对象json、jsonbJSON 对象、数组或标量

2. 基础类型

数字

PostgreSQL 的数字类型可以分为整数、精确小数和近似浮点数。它们在存储空间、取值范围和计算精度上各不相同:

类型空间范围或精度常见场景
smallint2 字节-32768 到 32767范围明确且较小的整数,例如优先级、评分
integer4 字节-2147483648 到 2147483647普通计数和编号,例如数量、页码
bigint8 字节-9223372036854775808 到 9223372036854775807可能超过 integer 范围的编号或计数,例如大型系统的主键
numeric(p, s) / decimal(p, s)可变精确十进制,p 为总位数,s 为小数位数金额、税率、需要精确舍入的业务小数
real4 字节约 6 位十进制有效数字,近似值对精度要求不高的测量值、模拟数据
double precision8 字节约 15 位十进制有效数字,近似值科学计算、统计分析、允许误差的坐标或比例

不要因为 bigint 范围更大就无条件使用它,也不要为了节省几个字节把所有数字都设为 smallint。integer 在范围、空间和性能之间比较均衡。只有已经知道数据规模会超过它的上限时,才需要选择 bigint。

小数需要区分精确值和近似值:

numeric-example.sql
1
CREATE TABLE prices (
2
amount numeric(12, 2),
3
confidence double precision
4
);

numeric(12, 2) 的精度是 12,标度是 2,也就是总共最多 12 位数字,其中小数部分保留 2 位,整数部分最多 10 位。写入更多小数位时,PostgreSQL 会先舍入到 2 位;如果舍入后的整数部分超过 10 位,则会报错。decimal 与 numeric 在 PostgreSQL 中是等价类型。

real 和 double precision 是浮点数,适合统计、测量等允许微小误差的场景。它们的计算通常比 numeric 更快,但保存的是二进制近似值,直接使用等号比较计算结果也可能得到意外结果。

金额不要使用浮点数。0.1 + 0.2 一类计算可能受到二进制浮点表示影响,而 numeric 会按十进制精确保存和计算。

PostgreSQL 还提供 money 类型,但它的显示格式和小数精度会受到区域设置影响,跨环境迁移和计算时更容易产生困惑。业务金额通常使用 numeric(p, s) 更清晰。

布尔

boolean 可以保存 true、false,如果列允许为空,还可以保存 NULL。因此,可空布尔列实际表达了三种状态。只有业务确实存在“未知”状态时才应该允许它为空,否则应配合 NOT NULL 和合理的默认值使用。

boolean-example.sql
1
CREATE TABLE boolean_example (
2
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
3
is_completed boolean NOT NULL DEFAULT false,
4
is_archived boolean
5
);

is_completed 是典型的二态字段:每一行都必须明确表示是否完成,省略该列时默认为 false。is_archived 没有设置 NOT NULL,因此还可以用 NULL 表示“尚未确定是否归档”。是否允许这种第三种状态,应由业务含义决定。

正在验证登录状态
请稍候,验证完成后将继续显示文章内容