PlanetScaleですでに運用されているものの型やカラム名を変更したいことがあります。
Prismaを利用しているとマイグレーションファイルを作って、それをDBに反映していくのですが、PlanetScaleではprisma db push
で変更することが推奨されます。
その手順は以下です。
今回はSiteモデルのurlをvarchar(191)
(prismaのStringのデフォルト)からvarchar(8190)
(Apacheが受け付けられるURLの長さのデフォルト)へ変更したいと思います。
model Site {
id Int @id @default(autoincrement())
name String
url String
}
1. データを一時退避させるカラムを作成してpushする
model Site {
id Int @id @default(autoincrement())
name String
url String
tempUrl String? @db.VarChar(1048)
}
これをnpx prisma db push
で適用します。
2. データをコピーしてsiteのurlをnullにする
const records = await prisma.site.findMany({
where: {
tempUrl: null,
},
select: {
id: true,
url: true,
},
});
const updatePromises = records.map(record => {
return prisma.site.update({
where: { id: record.id },
data: { tempUrl: record.url, url: null},
});
});
3. siteのurlカラムを削除する
model Site {
id Int @id @default(autoincrement())
name String
tempUrl String? @db.VarChar(1048)
}
これをnpx prisma db push
します。
4. siteのurlカラムを再構築する
今度はurlを@db.VarChar(1048)
で再構築します。
その際、urlは一旦String?
で構築します。
model Site {
id Int @id @default(autoincrement())
name String
url String? @db.VarChar(1048)
tempUrl String? @db.VarChar(1048)
}
これをnpx prisma db push
で適用します。
5. tempUrlの情報をurlに移行する
const records = await prisma.site.findMany({
where: {
url: null,
},
select: {
id: true,
tempUrl: true,
},
});
const updatePromises = records.map(record => {
return prisma.site.update({
where: { id: record.id },
data: { url: record.tempUrl, tempUrl: null},
});
});
6. tempUrlを削除し、urlはNullを許容しないように設定
urlはString
に変更し、tempUrlは削除します。
データが全て入っていればNOT NULL
への変更は可能みたいです。
model Site {
id Int @id @default(autoincrement())
name String
url String @db.VarChar(1048)
}
これをnpx prisma db push
で適用します。
手順が複雑でヒューマンエラーが起きそうですが、一応これが推奨みたいです。