マイグレーション
本チャプターでは、Prismaのマイグレーション機能を確認していきます。
Prismaは、マイグレーションを宣言的に利用でき、かなり使いやすいです。
スキーマ設定実施
prisma/schema.prisma
にユーザテーブルの定義を追加する
TypeScriptの型表現式を用いて、テーブル定義を表現する。
model User {
id Int @default(autoincrement()) @id
email String @unique
name String?
}
テーブル生成
以下コマンドを発行し、テーブルを生成を行う(DB初期マイグレーション)
npx prisma migrate dev --name init
SQLログを確認すると、以下コマンドが発行され、テーブルが作成される
CREATE TABLE "User" (
"id" SERIAL NOT NULL,
"email" TEXT NOT NULL,
"name" TEXT,
PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "User.email_unique" ON "User"("email");
PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "User.email_unique" ON "User"("email");
prisma/migrations/${timestamp}_init/migration.sql
でも、発行されたSQLは確認できます。
-- CreateTable
CREATE TABLE "User" (
"id" SERIAL NOT NULL,
"email" TEXT NOT NULL,
"name" TEXT,
PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "User.email_unique" ON "User"("email");
マイグレーション確認
- カラム追加
- 桁変更
- 属性変更(Not Null)
- テーブル追加
- 初期データ投入
1. カラム追加
ユーザテーブルに電話番号を追加
prisma/schema.prisma
を以下の通り修正
model User {
id Int @default(autoincrement()) @id
email String @unique
name String?
tel String? <--- 追加
}
- 変更反映
npx prisma migrate dev --name add_tel_to_user
以下SQLが発行され、変更が反映される
StringはTEXT型にマッピングされる
2021-05-16 05:03:13.632 UTC [2225] LOG: statement: -- AlterTable
ALTER TABLE "User" ADD COLUMN "tel" TEXT;
- マイグレーションファイル一覧
以下のようにマイグレーションファイルが追加生成される。
% find ./prisma/migrations | sort | sed '1d;s/^\.//;s/\/\([^/]*\)$/|--\1/;s/\/[^/|]*/| /g'
/Users/hirosue/workspace/hello-prisma
| | |--20210515111505_init
| | | |--migration.sql
| | |--20210516050313_add_tel_to_user <-- 追加
| | | |--migration.sql <-- 追加
| | |--migration_lock.toml
2. 桁変更
TEXT型 で定義されたカラムを修正する。
prisma/schema.prisma
を以下の通り修正
model User {
id Int @default(autoincrement()) @id
email String @unique
name String?
tel String? @db.VarChar(11) <--- ☆☆☆ 修正
}
- 変更反映
npx prisma migrate dev --name set_max_length_tel
以下SQLが発行され、変更が反映される
2021-05-16 05:36:11.585 UTC [2368] LOG: statement: /*
Warnings:
- You are about to alter the column `tel` on the `User` table. The data in that column could be lost. The data in that column will be cast from `Text` to `VarChar(11)`.
*/
-- AlterTable
ALTER TABLE "User" ALTER COLUMN "tel" SET DATA TYPE VARCHAR(11);
- マイグレーションファイル一覧
以下のようにマイグレーションファイルが追記される。
% find ./prisma/migrations | sort | sed '1d;s/^\.//;s/\/\([^/]*\)$/|--\1/;s/\/[^/|]*/| /g'
/Users/hirosue/workspace/hello-prisma
| | |--20210515111505_init
| | | |--migration.sql
| | |--20210516050313_add_tel_to_user
| | | |--migration.sql
| | |--20210516053611_set_max_length_tel <-- 追加
| | | |--migration.sql <-- 追加
| | |--migration_lock.toml
3. 属性変更(Not Null)
名前を Not Null へ変更
prisma/schema.prisma
を以下の通り修正
model User {
id Int @default(autoincrement()) @id
email String @unique
name String <--- ☆☆☆ 修正
tel String? @db.VarChar(11)
}
- 変更反映
npx prisma migrate dev --name set_not_null_name
以下SQLが発行され、変更が反映される
2021-05-16 05:42:07.761 UTC [2386] LOG: statement: /*
Warnings:
- Made the column `name` on table `User` required. This step will fail if there are existing NULL values in that column.
*/
-- AlterTable
ALTER TABLE "User" ALTER COLUMN "name" SET NOT NULL;
- マイグレーションファイル一覧
% find ./prisma/migrations | sort | sed '1d;s/^\.//;s/\/\([^/]*\)$/|--\1/;s/\/[^/|]*/| /g'
/Users/hirosue/workspace/hello-prisma
| | |--20210515111505_init
| | | |--migration.sql
| | |--20210516050313_add_tel_to_user
| | | |--migration.sql
| | |--20210516053611_set_max_length_tel
| | | |--migration.sql
| | |--20210516054207_set_not_null_name <---- 追加
| | | |--migration.sql <---- 追加
| | |--migration_lock.toml
4. テーブル追加
ユーザに紐づく投稿テーブルを追加する。
prisma/schema.prisma
を以下の通り修正
model User {
id Int @id @default(autoincrement())
email String @unique
name String
tel String? @db.VarChar(11)
posts Post[] <---- ☆☆☆ 修正
}
// 追加
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User? @relation(fields: [authorId], references: [id])
authorId Int?
}
- 変更反映
npx prisma migrate dev --name add_post
以下SQLが発行され、変更が反映される
2021-05-16 05:47:49.051 UTC [2403] LOG: statement: -- CreateTable
CREATE TABLE "Post" (
"id" SERIAL NOT NULL,
"title" TEXT NOT NULL,
"content" TEXT,
"published" BOOLEAN NOT NULL DEFAULT false,
"authorId" INTEGER,
PRIMARY KEY ("id")
);
-- AddForeignKey
ALTER TABLE "Post" ADD FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
5. 初期データ投入
prisma/seed.ts
ファイルを作成し、以下の内容を記載する
コードで初期データをセットアップする
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
const posts:any = []
for(let i = 0; i < 100; i++) {
posts.push({ title: `title ${i + 1}`})
}
async function main() {
const alice = await prisma.user.create({
data: {
name: 'Alice',
email: 'alice@example.com',
posts: {
create: posts
}
}
})
const bob = await prisma.user.create({
data: {
name: 'Bob',
email: 'bob@example.com',
posts: {
create: {
title: 'Check out Prisma with Next.js',
}
}
}
})
console.log({alice, bob})
}
main()
.catch(e => {
console.error(e)
process.exit(1)
})
.finally(async () => {
await prisma.$disconnect()
})
初期データ投入
% npx prisma db seed --preview-feature
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Running ts-node "prisma/seed.ts" ...
{
alice: { id: 1, email: 'alice@example.com', name: 'Alice', tel: null },
bob: { id: 2, email: 'bob@example.com', name: 'Bob', tel: null }
}
🌱 Your database has been seeded.
ちなみに、以下の部分は
const bob = await prisma.user.create({
data: {
name: 'Bob',
email: 'bob@example.com',
posts: {
create: {
title: 'Check out Prisma with Next.js',
}
}
}
})
こんな感じに自動的にトランザクションを発行し、ACID特性のAtomicity(原子性)を担保してくれる
2021-05-16 10:44:45.102 UTC [2999] LOG: statement: BEGIN
2021-05-16 10:44:45.103 UTC [2999] LOG: execute s0: INSERT INTO "postgres"."User" ("email","name") VALUES ($1,$2) RETURNING "postgres"."User"."id"
2021-05-16 10:44:45.103 UTC [2999] DETAIL: parameters: $1 = 'bob@example.com', $2 = 'Bob'
2021-05-16 10:44:45.105 UTC [2999] LOG: execute s1: INSERT INTO "postgres"."Post" ("title","published","authorId") VALUES ($1,$2,$3) RETURNING "postgres"."Post"."id"
2021-05-16 10:44:45.105 UTC [2999] DETAIL: parameters: $1 = 'Check out Prisma with Next.js', $2 = 'f', $3 = '2'
2021-05-16 10:44:45.106 UTC [2999] LOG: execute s2: SELECT "postgres"."User"."id", "postgres"."User"."email", "postgres"."User"."name", "postgres"."User"."tel" FROM "postgres"."User" WHERE "postgres"."User"."id" = $1 LIMIT $2 OFFSET $3
2021-05-16 10:44:45.106 UTC [2999] DETAIL: parameters: $1 = '2', $2 = '1', $3 = '0'
2021-05-16 10:44:45.108 UTC [2999] LOG: statement: COMMIT
反映確認
Prismaは、ブラウザ上で動作するGUIのツール(Prisma Studio
)も提供している。
npx prisma studio
記事データが101件登録されていることが確認できる。
現状、Prisma StudioにSQL発行機能はなさそう。