目录 3 章

PostgreSQL数据库 第 3 / 3 章

用于字段的数据类型

1513 字 · 约 6 分钟

用在字段(列)上的数据类型,核心原则是必须是在磁盘上有明确存储表示的类型。因此,PostgreSQL 的伪类型(Pseudo-Types),如 anyelement、trigger、internal 等,绝对不可以用作字段类型,它们仅用于定义函数参数或返回值。

排除伪类型后,可用在字段上的数据类型及具体要求如下。


🔢 数值类型#

类型存储/范围核心要求与说明
smallint2字节,-32768 至 +32767范围最窄,仅在磁盘空间极度敏感时使用
integer4字节,-2147483648 至 +2147483647最常用的整数类型,在范围、存储和性能间平衡最佳
bigint8字节,约 ±9.22×10¹⁸仅在 integer 范围不足时使用,性能略低于 integer
numeric(p, s)变长,精确p(精度)最大 1000;s(标度)范围 -1000 到 1000;金额等精确计算必选,但运算速度慢
real4字节,不精确约 6 位十进制有效数字,仅用于可接受舍入误差的科学计算
double precision8字节,不精确约 15 位十进制有效数字,精度高于 real,仍不精确
serial / bigserial语法糖自动创建序列并设置 DEFAULT nextval(...),不是真正的独立类型,底层是 integer / bigint

numeric 的精度与标度:p 是总有效位数,s 是小数点后的位数。NUMERIC(8, 2) 表示总共 8 位数字,其中小数点后 2 位,因此整数部分最多 6 位。如果存入的值标度大于声明值,系统会自动四舍五入到声明的小数位。


📝 字符类型#

类型长度要求行为与说明
varchar(n)n 必须 > 0 且 ≤ 10,485,760(约 10MB)变长,有上限;超长值在显式转换时会被截断而不报错
varchar / text无长度声明变长,理论上限约 1GB;绝大多数场景的首选,无需强行设定上限
char(n)n 必须 > 0 且 ≤ 10,485,760定长,不足部分用空格填充;char 不带长度等价于 char(1);现代应用极少使用

🕒 日期与时间类型#

time、timestamp 和 interval 均支持可选的精度 p,用于控制秒的小数部分位数。

  • p 的取值范围:0 到 6(默认使用微秒精度,即 p=6)。
  • date:无精度参数,仅存储年月日。
  • timestamptz:记录“时间点”的首选。它内部以 UTC 存储,显示时按会话时区转换,能正确处理跨时区数据。
  • timestamp:不带时区,存储的是“墙上时钟”字面值,不随时区转换。
  • interval:表示时间间隔,同样支持 p 来限制秒的小数位精度。

🚀 JSON 类型#

类型字段层面的核心要求
json保留输入文本的精确副本(含空格、键序),不支持索引,查询时需重新解析,性能差。
jsonb字段首选。二进制分解存储,支持 GIN 索引,查询性能远高于 json。但写入时有转换开销,且不保留键序与空格。

jsonb 字段的约束实践:可以在 jsonb 列上使用 CHECK 约束来强制某些键的存在或值的格式。对于高频查询的 jsonb 路径,需要创建表达式索引(如 CREATE INDEX ... ON tbl ((data->>'key')))或对整个列创建 GIN 索引,否则查询将全表扫描。


📦 数组类型#

  • 定义语法:在任意可用作字段的基础类型后加 [],如 integer[]、text[][]。可以创建内置类型、枚举、复合类型、范围或域的数组。
  • 维度与长度:声明时的维度(如 [3][3])和长度仅为文档说明,PostgreSQL 不会强制执行。但插入多维数组时,每个维度的长度必须严格匹配,否则报错。
  • 元素类型一致性:一个数组字段中的所有元素必须属于同一种数据类型。

🎯 用户定义类型(字段层面的特殊要求)#

枚举(ENUM)

  • 标签长度限制:每个枚举值(标签)的最大长度受编译参数 NAMEDATALEN 限制,标准安装下为 63 字节。
  • 排序内在性:枚举值按声明顺序排序,这会影响 ORDER BY 和范围比较的结果。
  • 适用边界:仅适用于封闭、稳定、极少变更的固定值集合(如订单状态)。频繁增删枚举值需要 ALTER TYPE,不适合动态性强的场景。

域(DOMAIN) 域是带约束的基础类型,用于将字段级别的通用约束(如 NOT NULL、CHECK)集中管理。

  • 可附加的约束:NOT NULL / NULL、CHECK (expression) 以及 DEFAULT 默认值。
  • 约束检查时机:域上的 NOT NULL 和 CHECK 约束在值被转换为域类型时进行检查。
  • 字段可用性:域完全可以作为字段类型使用,它是将业务规则抽象到类型层面的有效手段(例如定义一个 email_address 域,自带格式校验 CHECK 约束)。

范围(RANGE) 与 复合(COMPOSITE) int4range、daterange、tstzrange 等范围类型,以及通过 CREATE TYPE ... AS (...) 定义的复合类型,都可以直接用作字段类型,无额外字段级限制。范围类型用于高效表达连续区间,复合类型用于将多个相关属性打包为一个逻辑单元。


💎 快速核对清单#

你需要确保的事对应要求
绝不使用伪类型建列anyelement、trigger、internal、record(仅函数上下文)等均不可作为字段类型
金额计算用 numeric(p, s),p ≤ 1000,s 在 -1000 ~ 1000
字符串默认用 text 或 varchar;若用 varchar(n),n ≤ 10,485,760
时间点优先 timestamptz;需要秒的小数位精度时,p 在 0 ~ 6
JSON默认 jsonb;高频查询路径必须配套 GIN 或表达式索引
数组维度/长度声明不强制,但插入时维度必须匹配
枚举标签长度 ≤ 63 字节(标准安装);仅用于稳定封闭的集合

← 返回目录