Prisma迁移int自增ID为String类型UUID及重赋值方案咨询
问题说明
需求为将数据库中Int类型自增ID列转换为String格式的UUID,初始修改Prisma Schema的代码如下:
id Int @id @default(autoincrement()) // 改为 id String @id @default(uuid())
按上述方式修改后迁移可正常执行,但原有ID仅被转换为字符串格式的序列值(如'1'、'2'),并未重置为标准UUID。
出现该现象的原因是:字段类型迁移时只会做存量值的类型兼容转换,@default(uuid())规则仅对迁移完成后新插入的记录生效,不会主动覆盖已有数据的值。
待确认的问题点:
uuid()函数的算法实现来源与所属架构层级:由数据库、Rust层还是客户端生成?- 为存量数据重新赋值UUID的最佳方案是什么?
- 是否可以在Node客户端侧生成UUID?是否支持通过客户端API直接调用Prisma内置的UUID生成能力?
根据官方公开说明:
手动修改Prisma Schema并生成Prisma Client后,即使使用内省功能也可以使用
uuid(),此时UUID值由Prisma的查询引擎生成。
具体解答
1. uuid()的生成层级说明
Prisma的@default(uuid())默认值既不在数据库层生成,也不是Node客户端侧的JS/TS代码生成,而是由Prisma用Rust编写的查询引擎(Query Engine)在处理写入请求时生成,生成完成后再把UUID传给数据库执行写入。
目前Prisma没有暴露直接调用内置UUID生成方法的客户端API,无法在Node侧代码里直接调用Prisma内置的UUID生成函数。
2. 存量ID转UUID的最佳实操步骤
不要直接修改原ID字段类型跑迁移,按以下步骤操作可避免数据错乱:
- 第一步:给目标表新增一个String类型的临时字段,设置唯一约束和
@default(uuid()),例如命名为new_id,其余字段保持不变
model YourModel { id Int @id @default(autoincrement()) new_id String @unique @default(uuid()) // 其余原有字段、关联关系保持不变 }
- 第二步:执行迁移,此时所有存量记录的
new_id字段会被自动填充为标准UUID,后续新插入的记录也会自动生成符合规范的new_id - 第三步:处理所有关联表的外键:把所有关联原Int类型ID的外键值,匹配替换为对应主表记录的
new_id值,同步把外键字段类型修改为String - 第四步:删除原Int类型的
id字段,将new_id字段重命名为id,设置为主键
model YourModel { id String @id @default(uuid()) // 其余字段、外键关联均已同步调整为String类型UUID }
- 第五步:生成并执行最终迁移,校验所有表关联关系、数据查询写入正常即可。
3. Node客户端侧生成UUID的方案
完全可以在Node侧自行生成UUID,不需要依赖Prisma的内置生成能力,实操非常简单:
- 安装UUID依赖:
npm install uuid,TS项目额外安装类型包npm install -D @types/uuid - 业务代码中直接调用即可生成符合RFC4122标准的v4 UUID:
import { v4 as uuidv4 } from 'uuid'; // 生成UUID const recordId = uuidv4();
如果选择客户端侧生成ID,可以把Schema中ID字段的@default(uuid())移除,写入记录时手动传入生成的UUID即可,自行生成的UUID和Prisma内置生成的格式完全一致,不存在兼容性问题。
内容的提问来源于stack exchange,提问作者tkowt

