PGSQL数据类型详细说明
- [PostgreSQL 数据库数据类型详细说明](#PostgreSQL 数据库数据类型详细说明)
-
- 一、数值类型
-
- [1. 整数类型](#1. 整数类型)
- [2. 任意精度数值类型](#2. 任意精度数值类型)
- [3. 浮点类型(近似计算)](#3. 浮点类型(近似计算))
- 二、字符类型
-
- [1. 定长字符类型](#1. 定长字符类型)
- [2. 变长字符类型](#2. 变长字符类型)
- 三、日期时间类型
-
- [1. 日期与时间](#1. 日期与时间)
- [2. 时间间隔类型](#2. 时间间隔类型)
- 四、布尔类型
- 五、二进制类型
- 六、复杂类型
-
- [1. 数组类型](#1. 数组类型)
- [2. 复合类型](#2. 复合类型)
- [3. 范围类型](#3. 范围类型)
- [七、JSON 类型](#七、JSON 类型)
- 八、其他常用类型
-
- [1. UUID 类型](#1. UUID 类型)
- [2. 网络地址类型](#2. 网络地址类型)
- [3. 枚举类型(Enum)](#3. 枚举类型(Enum))
- [PostgreSQL 场景化数据类型选择指南](#PostgreSQL 场景化数据类型选择指南)
PostgreSQL 数据库数据类型详细说明
PostgreSQL 提供了丰富的数据类型,覆盖数值、字符、日期时间、布尔、二进制、复杂结构等多种场景,支持自定义类型和扩展。以下是按类别整理的详细说明,包含定义、存储特性、取值范围、使用示例 及注意事项。
一、数值类型
用于存储整数、小数、高精度数值等,支持精确计算和近似计算。
1. 整数类型
| 类型 | 别名 | 存储大小 | 取值范围 | 描述 |
|---|---|---|---|---|
smallint |
int2 |
2字节 | -32768 ~ 32767 | 小范围整数 |
integer |
int/int4 |
4字节 | -2147483648 ~ 2147483647 | 常用整数(默认整数类型) |
bigint |
int8 |
8字节 | -9223372036854775808 ~ 9223372036854775807 | 大范围整数 |
serial |
serial4 |
4字节 | 1 ~ 2147483647 | 自增整数(等价于 integer + 序列) |
bigserial |
serial8 |
8字节 | 1 ~ 9223372036854775807 | 大范围自增整数(等价于 bigint + 序列) |
示例:
sql
-- 创建自增ID表(serial自动关联序列)
CREATE TABLE users (
id serial PRIMARY KEY, -- 等价于 id integer NOT NULL DEFAULT nextval('users_id_seq')
age smallint CHECK (age > 0), -- 小范围整数(年龄)
score bigint -- 大范围整数(积分)
);
-- 插入数据(id自动生成)
INSERT INTO users (age, score) VALUES (25, 10000000000);
2. 任意精度数值类型
| 类型 | 别名 | 存储大小 | 描述 |
|---|---|---|---|
numeric |
decimal |
可变(最大131072位数字,16383位小数) | 高精度小数,适合财务、货币计算(无精度损失),语法:numeric(precision, scale) |
参数说明:
precision:总位数(1~1000,默认1000)scale:小数位数(0~precision,默认0)
示例:
sql
-- 创建财务表(精确到分)
CREATE TABLE orders (
id serial PRIMARY KEY,
amount numeric(10, 2) -- 总10位,小数2位(最大99999999.99)
);
INSERT INTO orders (amount) VALUES (12345678.90); -- 正确
INSERT INTO orders (amount) VALUES (123456789.12); -- 错误(总位数超过10)
3. 浮点类型(近似计算)
| 类型 | 别名 | 存储大小 | 取值范围(近似) | 精度损失 | 描述 |
|---|---|---|---|---|---|
real |
float4 |
4字节 | ±1.18×10⁻³⁸ ~ ±3.4×10³⁸ | 6位小数 | 单精度浮点数 |
double precision |
float8 |
8字节 | ±2.23×10⁻³⁰⁸ ~ ±1.8×10³⁰⁸ | 15位小数 | 双精度浮点数(默认浮点类型) |
注意 :浮点类型存在舍入误差,不适合财务等精确计算 ,优先用 numeric。
示例:
sql
CREATE TABLE sensors (
id serial PRIMARY KEY,
temperature real, -- 单精度(如传感器读数)
pressure double precision -- 双精度(如气压)
);
INSERT INTO sensors (temperature, pressure) VALUES (36.5, 1013.25);
二、字符类型
用于存储文本数据,支持定长、变长和无长度限制类型。
1. 定长字符类型
| 类型 | 存储大小 | 描述 |
|---|---|---|
char(n) |
n字节(不足补空格) | 定长字符串,n为长度(1~10485760),超出截断,适合固定长度数据(如身份证号) |
示例:
sql
CREATE TABLE products (
code char(8) PRIMARY KEY, -- 定长8位编码(如"PROD1234")
name varchar(50)
);
INSERT INTO products (code, name) VALUES ('ABC12345', '商品A'); -- code存储为'ABC12345'(8位,无空格)
INSERT INTO products (code, name) VALUES ('AB', '商品B'); -- code存储为'AB '(补6个空格)
2. 变长字符类型
| 类型 | 别名 | 存储大小 | 描述 |
|---|---|---|---|
varchar(n) |
character varying(n) |
变长(实际长度+1或4字节 overhead) | 最大n个字符(n≤10485760),超出报错,适合长度有限的文本(如用户名) |
text |
- | 变长(实际长度+1或4字节 overhead) | 无长度限制的可变字符串,适合长文本(如文章内容) |
注意 :varchar(n) 和 text 性能接近,优先用 text(更简洁);varchar 不带长度时等价于 text。
示例:
sql
CREATE TABLE articles (
id serial PRIMARY KEY,
title varchar(100), -- 标题(最长100字符)
content text -- 正文(无长度限制)
);
INSERT INTO articles (title, content) VALUES (
'PostgreSQL 数据类型',
'PostgreSQL 提供丰富的类型...'
);
三、日期时间类型
用于存储日期、时间、时间戳及时间间隔,支持时区处理。
1. 日期与时间
| 类型 | 存储大小 | 格式示例 | 描述 |
|---|---|---|---|
date |
4字节 | 2024-05-20 |
日期(年-月-日) |
time [without time zone] |
8字节 | 15:30:45 |
时间(时:分:秒,无时区) |
time with time zone |
12字节 | 15:30:45+08 |
带时区的时间(如北京时间+08) |
timestamp [without time zone] |
8字节 | 2024-05-20 15:30:45 |
时间戳(日期+时间,无时区) |
timestamp with time zone |
8字节 | 2024-05-20 15:30:45+08 |
带时区的时间戳(存储为UTC,显示时转换为本地时区,推荐用此类型) |
常用函数:
current_date:当前日期(如2024-05-20)current_time:当前时间(带时区)current_timestamp:当前时间戳(带时区)now():等价于current_timestamp
示例:
sql
CREATE TABLE events (
id serial PRIMARY KEY,
event_name varchar(100),
start_time timestamp with time zone, -- 带时区的时间戳
duration interval -- 时间间隔(如'2 hours 30 minutes')
);
INSERT INTO events (event_name, start_time, duration) VALUES (
'产品发布会',
now(), -- 当前时间戳(带时区)
'2 hours' -- 间隔2小时
);
2. 时间间隔类型
| 类型 | 存储大小 | 格式示例 | 描述 |
|---|---|---|---|
interval |
16字节 | 1 year 2 months 3 days 4 hours 5 minutes 6 seconds |
时间间隔,支持年、月、日、时、分、秒等单位,可进行加减运算(如 timestamp + interval) |
示例:
sql
SELECT now() + interval '1 day 3 hours'; -- 当前时间加1天3小时
-- 结果:2024-05-21 18:30:45+08(假设当前是2024-05-20 15:30:45+08)
四、布尔类型
| 类型 | 存储大小 | 取值 | 描述 |
|---|---|---|---|
boolean |
1字节 | true/false/null |
布尔值,也可用 yes/no/on/off 代替(不区分大小写) |
示例:
sql
CREATE TABLE tasks (
id serial PRIMARY KEY,
task_name varchar(100),
completed boolean DEFAULT false -- 默认未完成
);
INSERT INTO tasks (task_name, completed) VALUES ('学习PostgreSQL', true);
五、二进制类型
| 类型 | 存储大小 | 描述 |
|---|---|---|
bytea |
可变(最大1GB) | 存储二进制数据(如图片、文件),支持转义字符串(如 \x1234abcd)或十六进制前缀(0x1234abcd) |
示例:
sql
CREATE TABLE files (
id serial PRIMARY KEY,
file_name varchar(100),
content bytea -- 存储文件二进制内容
);
-- 插入二进制数据(示例:插入一个简单文本文件的二进制)
INSERT INTO files (file_name, content) VALUES (
'test.txt',
E'\\x546573742066696C6520636F6E74656E74' -- 十六进制表示的"Test file content"
);
六、复杂类型
PostgreSQL 支持数组、复合类型、范围类型等复杂结构,满足多样化数据存储需求。
1. 数组类型
- 定义 :用
类型[]表示一维数组,类型[][]表示二维数组(最多支持多维)。 - 存储:可变长度,元素类型需一致。
- 构造 :用
ARRAY[元素1, 元素2]或'{元素1,元素2}'::类型[]。
示例:
sql
CREATE TABLE students (
id serial PRIMARY KEY,
name varchar(50),
scores integer[] -- 成绩数组(如一学期多门课成绩)
);
-- 插入数组数据
INSERT INTO students (name, scores) VALUES (
'张三',
ARRAY[90, 85, 95] -- 等价于 '{90,85,95}'::integer[]
);
-- 查询数组元素(第2门课成绩)
SELECT name, scores[2] FROM students WHERE id = 1; -- 结果:85
-- 数组函数:array_length(数组, 维度)
SELECT array_length(scores, 1) FROM students; -- 结果:3(数组长度)
2. 复合类型
- 定义 :用
CREATE TYPE创建自定义结构体,包含多个字段。 - 使用:可直接作为表列类型,或作为函数返回值。
示例:
sql
-- 创建复合类型(表示人员信息)
CREATE TYPE person AS (
name varchar(50),
age integer,
email varchar(100)
);
-- 创建表使用该类型
CREATE TABLE employees (
id serial PRIMARY KEY,
info person -- 复合类型列
);
-- 插入数据(用ROW构造复合类型值)
INSERT INTO employees (info) VALUES (
ROW('李四', 30, 'lisi@example.com') -- 等价于 (name=>'李四', age=>30, email=>'lisi@example.com')
);
-- 查询复合类型字段
SELECT (info).name, (info).age FROM employees; -- 结果:李四 | 30
3. 范围类型
用于表示连续的数值、日期等范围(如价格区间、日期区间),支持包含、重叠等操作。
| 类型 | 描述 | 示例范围值 |
|---|---|---|
int4range |
整数范围 | [1, 10)(含1不含10) |
numrange |
数值范围(numeric) | (3.14, 9.8] |
tsrange |
时间戳范围(无时区) | [2024-01-01 00:00, 2024-12-31 23:59] |
daterange |
日期范围 | [2024-05-01, 2024-05-31] |
示例:
sql
CREATE TABLE promotions (
id serial PRIMARY KEY,
discount numrange, -- 折扣范围(如[0.8, 0.9)表示8折到9折)
active_period daterange -- 活动日期范围
);
-- 插入范围数据(用'[)'表示左闭右开)
INSERT INTO promotions (discount, active_period) VALUES (
'[0.8, 0.9)',
'[2024-06-01, 2024-06-30]'
);
-- 查询范围是否重叠
SELECT * FROM promotions WHERE active_period && '[2024-06-15, 2024-07-15]'::daterange;
七、JSON 类型
用于存储 JSON 数据,支持两种类型:
| 类型 | 存储方式 | 描述 |
|---|---|---|
json |
文本存储 | 存储原始 JSON 字符串,不验证格式,查询时需解析,性能较低 |
jsonb |
二进制存储 | 解析并验证 JSON 格式,支持索引(GIN索引),推荐优先使用 |
常用操作:
- 插入:
'{"name": "Alice", "age": 25}'::jsonb - 提取字段:
jsonb_extract_path_text(column, 'name')或column->>'name' - 条件查询:
WHERE column @> '{"age": 25}'::jsonb(包含指定键值对)
示例:
sql
CREATE TABLE users (
id serial PRIMARY KEY,
profile jsonb -- 存储用户资料(JSON格式)
);
-- 插入JSON数据
INSERT INTO users (profile) VALUES (
'{"name": "Bob", "hobbies": ["reading", "coding"], "address": {"city": "Beijing", "zip": "100000"}}'::jsonb
);
-- 查询爱好包含"coding"的用户
SELECT id, profile->>'name' AS name
FROM users
WHERE profile->'hobbies' ? 'coding'; -- 结果:Bob
-- 创建GIN索引加速JSON查询
CREATE INDEX idx_profile ON users USING GIN (profile);
八、其他常用类型
1. UUID 类型
| 类型 | 存储大小 | 描述 |
|---|---|---|
uuid |
16字节 | 存储通用唯一标识符(UUID),格式如 a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11,推荐用 gen_random_uuid() 生成 |
示例:
sql
CREATE EXTENSION IF NOT EXISTS pgcrypto; -- 启用pgcrypto扩展(提供UUID生成函数)
CREATE TABLE devices (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), -- 自动生成UUID
name varchar(100)
);
INSERT INTO devices (name) VALUES ('传感器A');
2. 网络地址类型
| 类型 | 存储大小 | 描述 |
|---|---|---|
inet |
7~19字节 | IPv4/IPv6 地址(含子网掩码),如 192.168.1.1/24 |
cidr |
7~19字节 | IPv4/IPv6 子网(CIDR表示法),如 192.168.1.0/24 |
macaddr |
6字节 | MAC 地址(如 08:00:2b:01:02:03) |
示例:
sql
CREATE TABLE servers (
id serial PRIMARY KEY,
ip inet,
subnet cidr,
mac macaddr
);
INSERT INTO servers (ip, subnet, mac) VALUES (
'192.168.1.100/24',
'192.168.1.0/24',
'08:00:2b:01:02:03'
);
3. 枚举类型(Enum)
用户自定义的离散值集合,确保字段值只能是预设选项之一。
示例:
sql
-- 创建枚举类型(表示订单状态)
CREATE TYPE order_status AS ENUM ('pending', 'paid', 'shipped', 'delivered');
CREATE TABLE orders (
id serial PRIMARY KEY,
status order_status DEFAULT 'pending'
);
INSERT INTO orders (status) VALUES ('paid'), ('shipped');
-- INSERT INTO orders (status) VALUES ('invalid'); -- 报错(值不在枚举中)
PostgreSQL 场景化数据类型选择指南
PostgreSQL 数据类型的选择需结合业务场景特性 (如数据精度、长度、变化频率)、性能需求 (存储效率、查询速度)和数据完整性 (约束、唯一性)。以下按常见业务场景分类,给出针对性选型建议,附推荐类型、理由、示例代码 及避坑指南。
一、用户信息场景(姓名、手机号、邮箱等)
场景特点
- 数据长度有限(姓名通常≤50字符,手机号11~15位,邮箱≤254字符);
- 需支持模糊查询(如按姓名搜索)、唯一性约束(如手机号唯一);
- 避免存储冗余空格,注重可读性。
推荐数据类型
| 字段 | 推荐类型 | 理由 | 示例代码 |
|---|---|---|---|
| 姓名 | varchar(50) |
变长存储(避免定长补空格),长度覆盖绝大多数姓名(含复姓、少数民族名) | CREATE TABLE users (id serial, name varchar(50) NOT NULL); |
| 手机号 | varchar(15) |
支持国际区号(如+86 13800138000),变长灵活;不用char(补空格影响查询) | ALTER TABLE users ADD COLUMN phone varchar(15) UNIQUE; |
| 邮箱 | varchar(254) |
遵循RFC标准(邮箱最大长度254字符),变长存储 | ALTER TABLE users ADD COLUMN email varchar(254) UNIQUE CHECK (email LIKE '%@%'); |
| 性别 | enum 或 char(1) |
枚举类型(enum)限制取值(如'm'/'f'/'u'),char(1)更简洁(如'男'/'女'用'M'/'F') |
CREATE TYPE gender AS ENUM ('male', 'female', 'unknown'); ALTER TABLE users ADD COLUMN gender gender; |
避坑指南
- ❌ 不用
text存储手机号/邮箱:text无长度限制,可能因误操作存入超长无效数据(如手机号输成20位); - ❌ 不用
int存储手机号:国内手机号含前导0(如010-xxxxxxx),且国际号码有+号,整数会丢失符号; - ✅ 加唯一约束:
UNIQUE确保手机号/邮箱不重复(如phone varchar(15) UNIQUE)。
二、财务/交易场景(金额、价格、积分等)
场景特点
- 需精确计算(无舍入误差),避免浮点精度丢失(如0.1+0.2≠0.3);
- 金额通常有固定小数位(如人民币2位,美元2位);
- 需支持大额数值(如企业级交易可能超千万)。
推荐数据类型
| 字段 | 推荐类型 | 理由 | 示例代码 |
|---|---|---|---|
| 金额(人民币) | numeric(12,2) |
总12位(含2位小数),最大9999999999.99(百亿级),精确无误差 | CREATE TABLE orders (id serial, amount numeric(12,2) NOT NULL CHECK (amount >= 0)); |
| 积分 | bigint |
积分可能超千万(如用户长期积累),bigint 范围(-9e18~9e18)足够 |
ALTER TABLE users ADD COLUMN points bigint DEFAULT 0; |
| 汇率 | numeric(10,6) |
汇率通常保留6位小数(如1美元=6.897500人民币),numeric 精确存储 |
CREATE TABLE exchange_rates (currency varchar(3), rate numeric(10,6)); |
避坑指南
- ❌ 绝对不用
float/double precision:浮点类型存在舍入误差(如0.1::float8 * 3结果可能为0.30000000000000004),导致财务对账错误; - ✅ 加约束:
CHECK (amount >= 0)确保金额非负,CHECK (scale(rate,6) = rate)限制汇率小数位; - ✅ 索引优化:对高频查询的金额字段(如
amount > 1000)建B-tree索引。
三、日志/文本存储场景(操作日志、文章内容、评论)
场景特点
- 文本内容长度差异大(日志可能几百字,文章可能几万字);
- 需支持全文检索(如搜索日志关键词);
- 写入频繁,读取相对较少(日志场景)。
推荐数据类型
| 字段 | 推荐类型 | 理由 | 示例代码 |
|---|---|---|---|
| 操作日志 | text |
无长度限制,变长存储,适合长日志(如错误堆栈) | CREATE TABLE operation_logs (id serial, content text, created_at timestamptz); |
| 文章内容 | text + tsvector |
text 存储正文,tsvector 类型配合全文索引(GIN)加速搜索 |
ALTER TABLE articles ADD COLUMN search_vector tsvector GENERATED ALWAYS AS (to_tsvector('english', content)) STORED; CREATE INDEX idx_article_search ON articles USING GIN(search_vector); |
| 短评论 | varchar(500) |
限制长度(避免刷屏),变长存储 | ALTER TABLE comments ADD COLUMN content varchar(500) NOT NULL; |
避坑指南
- ❌ 不用
char(n)存储日志/文章:定长会浪费大量存储空间(如100字日志用char(1000)会补900空格); - ✅ 全文检索优化:用
tsvector类型存储分词结果,配合GIN索引(查询速度提升10倍以上); - ✅ 分区表:日志表按时间分区(如按月),避免单表过大影响查询性能。
四、JSON/半结构化数据场景(用户配置、动态表单、API响应)
场景特点
- 数据结构不固定(如用户自定义配置项);
- 需支持嵌套字段查询(如
config->'theme'->>'color'); - 高频读写,需兼顾存储效率和查询性能。
推荐数据类型
| 字段 | 推荐类型 | 理由 | 示例代码 |
|---|---|---|---|
| 用户配置 | jsonb |
二进制存储(比 json 省空间),支持索引(GIN)、字段校验、高效查询 |
CREATE TABLE user_configs (user_id int, config jsonb NOT NULL); CREATE INDEX idx_config_theme ON user_configs USING GIN ((config->'theme')); |
| 动态表单 | jsonb |
存储表单字段(如 {"fields": [{"name":"age","type":"number"}]}) |
ALTER TABLE forms ADD COLUMN schema jsonb; |
避坑指南
- ❌ 不用
json存储高频访问数据:json是文本存储,查询时需解析,性能比jsonb低50%+; - ✅ 用
jsonb_path_ops索引:对JSON字段的键值对查询(如config @> '{"theme":"dark"}')用GIN(jsonb_path_ops)索引更高效; - ✅ 加约束:用
CHECK (jsonb_typeof(config) = 'object')确保JSON为对象类型(非数组/字符串)。
五、唯一标识场景(主键、订单号、设备ID)
场景特点
- 需全局唯一(避免分布式系统ID冲突);
- 不希望暴露业务增长(如自增ID可被猜测订单量);
- 需支持分布式生成(如多服务实例同时生成ID)。
推荐数据类型
| 字段 | 推荐类型 | 理由 | 示例代码 |
|---|---|---|---|
| 主键ID | uuid |
全局唯一(128位),随机生成(如 gen_random_uuid()),不暴露业务量 |
CREATE EXTENSION IF NOT EXISTS pgcrypto; <br> CREATE TABLE orders (id uuid PRIMARY KEY DEFAULT gen_random_uuid(), ...); |
| 订单号 | varchar(32) + uuid |
订单号需可读性(如含日期前缀),用 uuid 生成唯一部分(如 ORDER_${to_char(now(),'YYYYMMDD')}_${substr(gen_random_uuid()::text,1,8)}) |
`ALTER TABLE orders ADD COLUMN order_no varchar(32) UNIQUE DEFAULT 'ORDER_' |
| 设备ID | macaddr |
存储MAC地址(如 08:00:2b:01:02:03),专用类型校验格式 |
CREATE TABLE devices (id serial, mac macaddr UNIQUE, ...); |
避坑指南
- ❌ 不用
serial作为分布式系统主键:serial依赖单实例序列,分布式环境下可能冲突; - ✅ 用
uuid-ossp扩展:除pgcrypto外,uuid-ossp提供更多UUID生成方式(如uuid_generate_v1()基于时间戳); - ✅ 索引优化:
uuid主键默认建B-tree索引,查询效率与integer接近(因UUID随机分布,插入时索引分裂略多,可接受)。
六、时间序列场景(传感器数据、监控指标、日志时间戳)
场景特点
- 数据按时间顺序写入(高频写入,如每秒数千条);
- 需支持时间范围查询(如"近1小时数据")、聚合(如"每小时平均值");
- 数据量大(可能达TB级),需高效压缩和分区。
推荐数据类型
| 字段 | 推荐类型 | 理由 | 示例代码 |
|---|---|---|---|
| 时间戳 | timestamptz(带时区) |
存储UTC时间,显示时自动转换本地时区,避免时区混乱(如跨地域服务器) | CREATE TABLE sensor_data (id serial, device_id int, value numeric(10,2), ts timestamptz DEFAULT now()); |
| 时间范围 | tstzrange(带时区范围) |
表示连续时间段(如设备在线时段 [2024-05-20 08:00, 2024-05-20 18:00]) |
ALTER TABLE device_status ADD COLUMN online_period tstzrange; |
优化策略
- 分区表 :按时间分区(如按天/周),用
PARTITION BY RANGE (ts),查询时仅扫描目标分区; - 列式存储 :用
timescaledb扩展(PostgreSQL时序数据库插件),压缩率提升90%+,聚合查询提速100倍; - BRIN索引:对时间序列字段建BRIN索引(块范围索引),适合按时间范围查询(索引体积仅为B-tree的1/100)。
七、枚举/状态场景(订单状态、用户等级、开关标志)
场景特点
- 字段取值固定(如订单状态:待支付/已支付/已发货);
- 需限制非法值(如不允许"已支付"改为"待支付");
- 可读性优先(代码中直接用枚举名而非数字)。
推荐数据类型
| 字段 | 推荐类型 | 理由 | 示例代码 |
|---|---|---|---|
| 订单状态 | enum 类型 |
自定义枚举(如 order_status),取值固定,插入非法值时报错 |
CREATE TYPE order_status AS ENUM ('pending', 'paid', 'shipped', 'delivered'); ALTER TABLE orders ADD COLUMN status order_status DEFAULT 'pending'; |
| 开关标志 | boolean |
简单二值(如 is_active),存储1字节,查询效率高 |
ALTER TABLE users ADD COLUMN is_active boolean DEFAULT true; |
避坑指南
- ❌ 不用
varchar存储枚举值:易出现拼写错误(如"paid"写成"payed"),且无约束; - ✅ 枚举扩展:如需新增状态(如"退货中"),用
ALTER TYPE order_status ADD VALUE 'returning' AFTER 'delivered';(PostgreSQL 10+支持); - ✅ 状态流转约束:用触发器或应用层逻辑限制状态变更(如"已发货"不能直接改回"待支付")。
八、通用选择原则总结
- 精确优先于近似 :财务用
numeric,不用float;计数用integer/bigint,不用real。 - 长度明确用定长,否则用变长 :身份证号(18位)用
char(18),姓名用varchar(50),长文本用text。 - 唯一标识用
uuid:避免自增ID暴露业务量,支持分布式生成。 - JSON用
jsonb:二进制存储+索引支持,优于json文本存储。 - 时间用
timestamptz:带时区避免跨地域混乱,配合分区/BRIN索引优化时序查询。 - 枚举用
enum类型:限制取值,提升可读性和完整性。
通过以上场景化选型,可在数据准确性、存储效率、查询性能 间取得平衡,为业务系统奠定坚实的数据基础。实际应用中需结合具体业务调整(如超高频写入场景可考虑列式存储扩展),并通过 EXPLAIN ANALYZE 验证查询性能。