関連記事は⬇︎⬇︎

利用シーン
🎯 アプリケーションの起動に必要なデータ ( デフォルトの言語やデフォルトのジャンルなど ) をデータベースに一括入力できます。
🎯 開発環境でアプリケーションを検証して使用するための基本データを一括入力できます。
これは、開発データベースのリセットが必要になる場合がある Prisma Migrate を使用している場合に特に便利です。
prisma.seed キーを追加する
Prisma の統合シード機能は、package.json ファイルの prisma.seed キーに実行するコマンドを設定しておいて、prisma db seed がそれを実行します。
Line 7-9 を追加します。
// package.json
{
"name": "backend",
"version": "1.0.0",
"main": "index.js",
"prisma": {
"seed": "ts-node prisma/seed.ts"
},
...
プロジェクトの prisma フォルダー内にシード スクリプト( seed.ts ) を記述します。
仮に以下のように Daibunrui、Chubunrui テーブルがあるとします。
大分類データを先に入力し、各大分類別 中分類でーたを入力することを想定します。
// 大分類
model Daibunrui {
id Int @id @default(autoincrement())
name String @unique
daibunruis Chubunrui[]
}
// 中分類
model Chubunrui {
id Int @id @default(autoincrement())
name String @unique
daibunrui Daibunrui? @relation(fields: [daibunruiId], references: [id])
daibunruiId Int?
}
prisma/seed-sources.ts に入力データを作成します。(任意)
// prisma/seed-sources.ts
export const daibunrui = [
{ name: "HOGE" },
{ name: "FOO" },
{ name: "BAR" },
{ name: "BAZ" },
...
];
const hogeId = 1;
const fooId = 2;
const barId = 3;
const bazId = 4;
export const chubunrui = [
{ name: "hoge1", daibunruiId: hogeId },
{ name: "hoge2", daibunruiId: hogeId },
...
{ name: "foo1", daibunruiId: fooId },
{ name: "foo2", daibunruiId: fooId },
...
{ name: "bar1", daibunruiId: barId },
{ name: "bar2", daibunruiId: barId },
...
{ name: "baz1", daibunruiId: bazId },
{ name: "baz2", daibunruiId: bazId },
...
];
createMany() で一括入力できます。( SQLite はサポートしません )
skipDuplicates: true で重複データを排除します。
// prisma/seed.ts
import { PrismaClient } from "@prisma/client";
import { daibunrui, chubunrui } from "./seed-sources";
const prisma = new PrismaClient();
async function main() {
try {
await prisma.daibunrui.createMany({ data: [...daibunrui], skipDuplicates: true });
} catch (error) {
console.error(error);
} finally {
await prisma.chubunrui.createMany({ data: [...chubunrui], skipDuplicates: true });
}
}
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});
実行する
try🐶everything backend$ npx prisma db seed Environment variables loaded from .env Running seed command `ts-node prisma/seed.ts` ... 🌱 The seed command has been executed. try🐶everything backend$
確認する
npx prisma studio コマンドで Prisma Studio を実行して確認します。
デフォルトで 5555 ポートを使用しますが、Android エミュレーターも同じポートを利用するので変更しておくと良いと思います。
$ npx prisma studio -p 5505
リレーションのある表を投入するときの注意(2026 年 7 月 追記)
この記事を書いたあとに気づいた点が 2 つあります。本文のコードをそのまま使うと、状況によってうまくいきません。
1. finally ではなく、順番に実行する
本文の main() は、大分類の投入を try、中分類の投入を finally に置いています。
finally は「エラーが起きても起きなくても実行される」ブロックです。つまり大分類の投入に失敗しても、中分類を入れにいきます。参照先がない状態で外部キーを持つデータを入れることになるので、そこでまた失敗します。
依存関係があるデータは、素直に順番に書いてください。
async function main() {
await prisma.daibunrui.createMany({
data: daibunrui,
skipDuplicates: true,
});
await prisma.chubunrui.createMany({
data: chubunrui,
skipDuplicates: true,
});
}
エラー処理は末尾の .catch() がすでに担っているので、main() の中で握りつぶす必要はありません。途中で失敗したら止まるほうが、原因も分かりやすくなります。
2. ID を決め打ちしない
本文では、大分類の ID を次のように書いています。
const hogeId = 1;
const fooId = 2;
これは「autoincrement() で 1 から順に振られるはずだ」という前提です。まっさらなデータベースに一度だけ流すなら、そのとおりになります。
ただし、すでにデータが入っている環境では成り立ちません。autoincrement の採番は、行を削除しても戻りません。開発中にデータを消して入れ直した経験があれば、次の投入では 1 から始まらない可能性があります。気づかないまま、間違った親に紐づいたデータができあがります。
確実なのは、ID ではなく名前で結びつける書き方です。
// 大分類を入れてから、名前を手がかりに ID を引く
await prisma.daibunrui.createMany({
data: daibunrui,
skipDuplicates: true,
});
const parents = await prisma.daibunrui.findMany();
const idOf = Object.fromEntries(parents.map((p) => [p.name, p.id]));
await prisma.chubunrui.createMany({
data: [
{ name: 'hoge1', daibunruiId: idOf['HOGE'] },
{ name: 'foo1', daibunruiId: idOf['FOO'] },
],
skipDuplicates: true,
});
本文のモデル定義では name に @unique が付いているので、この方法が使えます。何度実行しても同じ結果になるのが利点です。
件数が少なければ、upsert を使って親子をまとめて書く方法もあります。どちらを選ぶかはデータ量次第です。
3. バージョンについて
この記事は 2023 年 10 月時点のものです。package.json に prisma.seed を書いて npx prisma db seed で実行する、という流れは変わっていません。
ただし createMany のオプション(skipDuplicates など)や、seed スクリプトの実行に使うツールの推奨は、Prisma のバージョンによって変わることがあります。お使いのバージョンの公式ドキュメントとあわせてご確認ください。
※ 1 と 2 は本文に掲載したコードを読み直して整理したものです。3 を含め、改めて動作検証を行ったものではありません。
コメント