PostgreSQL 13+才内置gen_random_uuid()函数,低版本需启用uuid-ossp扩展用uuid_generate_v4();v13+仍需CREATE EXTENSION IF NOT EXISTS "pgcrypto"确保可用;建表主键应设DEFAULT gen_random_uuid(),避免TEXT存储和重复调用导致冲突。

PostgreSQL 13+ 才能直接用 gen_random_uuid(),低于这个版本会报错“function gen_random_uuid() does not exist”
确认 PostgreSQL 版本是否支持 gen_random_uuid()
该函数是 PostgreSQL v13 内置的,不依赖扩展。低于 v13(比如 v12 或更早)即使装了 pgcrypto 也不存在这个函数。
- 检查版本:
SELECT version();—— 输出含13.或更高即支持 - v12 及以下必须改用
uuid_generate_v4()(需先启用"uuid-ossp"扩展)或手动安装pgcrypto后用其他方式生成随机字节再转 UUID - 别在跨版本迁移脚本里硬写
gen_random_uuid(),否则在旧库执行直接失败
启用 pgcrypto 扩展(v13+ 可跳过,但建表前仍建议确认)
gen_random_uuid() 依赖 pgcrypto 扩展提供底层随机数能力,虽然 v13+ 默认内置该函数,但某些精简版或容器镜像可能未加载扩展。
- 执行:
CREATE EXTENSION IF NOT EXISTS "pgcrypto"; - 注意双引号——
pgcrypto是标识符名,不是字符串,不加引号在部分配置下会报错 - 该命令需在目标数据库中单独运行,不是一次启用就全局生效;每个新数据库都要单独执行
- 如果提示
permission denied,说明当前用户无CREATEDB或EXTENSION权限,得找 DBA 授权
建表时设 DEFAULT gen_random_uuid() 作为主键
这是最常用、最安全的方式,插入时不传 id 字段即可自动生成。
- 正确写法:
id UUID PRIMARY KEY DEFAULT gen_random_uuid() - 不要写成
id UUID DEFAULT gen_random_uuid() PRIMARY KEY—— 语法虽通,但部分 ORM 或迁移工具解析异常 - 避免用
TEXT或VARCHAR(36)存 UUID:浪费空间、无法利用uuid类型的索引优化和校验 - 别在
INSERT ... SELECT中对同一行多次调用gen_random_uuid(),它每次返回值都不同,可能导致主键冲突或逻辑错乱
插入数据时显式调用 gen_random_uuid() 的注意事项
适用于需要预生成 ID、或与其它字段联动构造场景(如分片键),但要小心并发和重复。
- 单条插入可写:
INSERT INTO users (id, name) VALUES (gen_random_uuid(), 'alice'); - 批量插入慎用:
INSERT INTO users (id, name) SELECT gen_random_uuid(), name FROM temp_names;—— 每行都会独立生成,没问题;但若temp_names有重复name且业务依赖id顺序,则 UUID 无序性会影响后续处理 - 它不保证全局单调递增,也不能用于时间排序;如需“最近注册用户”,应额外维护
created_at字段 - 高并发下极少出现碰撞(理论概率约 10⁻³⁶),但若应用层做了重试逻辑,需确保重试时重新调用
gen_random_uuid(),而不是复用上次生成的值
真正容易被忽略的是:v13+ 虽内置函数,但很多生产环境仍在用 v12 或定制编译版,上线前务必在目标实例上实测 SELECT gen_random_uuid(); 是否返回合法 UUID 值,而不是只查文档或本地开发库版本。


















