はじめに
Prismaでseedデータを投入する際、何も考えずにcreateManyを実行すると以下のような状況になることがあります。
- uniqueキーがあればエラーになる
- uniqueキーがなければ実行のたびにレコードが増え続ける
これを回避するには、deleteManyで既存データを消してから投入する方法もありますが、既存データを保持したい場合には使えません。
そこで便利なのがskipDuplicatesオプションです。uniqueキーの重複時にエラーを出さずスキップしてくれるため、冪等(べきとう)なseed処理を実現できます。
await prisma.user.createMany({
data: [
{ email: "alice@example.com", name: "Alice" },
{ email: "bob@example.com", name: "Bob" },
],
skipDuplicates: true,
});
skipDuplicates vs deleteMany
筆者は前者のskipDuplicatesを使った冪等なseed処理を書くことが多いです。
後者はprisma migrate reset -fを実行すると同等の処理ができるため、使い分けをしています。
各データベースでのskipDuplicatesの挙動
ON CONFLICT DO NOTHINGはPostgreSQLでしかサポートされていないと見かけた気がしたので、skipDuplicatesは内部でどのようなSQLを発行しているのか気になったので各DBで確認しました。
PostgreSQL
INSERT INTO "public"."User" ("email","name")
VALUES ($1,$2), ($3,$4), ($5,$6)
ON CONFLICT DO NOTHING
PostgreSQLはON CONFLICT DO NOTHINGを使用しています。
MySQL / MariaDB
INSERT IGNORE INTO `prisma`.`User` (`email`,`name`)
VALUES (?,?), (?,?), (?,?)
MySQLとMariaDBはINSERT IGNOREを使用していました。
注意点: unique制約が必須
skipDuplicatesはuniqueフィールドまたはIDフィールドでのみ重複判定が行われます。
Do not insert records with unique fields or ID fields that already exist.
— Prisma Client Reference
model User {
id Int @id @default(autoincrement())
email String @unique // ← これが必要
name String?
}
unique制約がないフィールドで重複を避けたい場合、skipDuplicatesでは対応できません。その場合はupsertや事前の存在チェックが必要になります。
サポート状況
| Database | createMany | skipDuplicates | 内部実装 |
|---|---|---|---|
| PostgreSQL | ✅ | ✅ | ON CONFLICT DO NOTHING |
| MySQL | ✅ | ✅ | INSERT IGNORE |
| MariaDB | ✅ | ✅ | INSERT IGNORE |
| SQLite | ✅ | ❌ | - |
| MongoDB | ✅ | ❌ | - |
| SQL Server | ✅ | ❌ | - |
Prismaのドキュメントには以下のように記載されています:
Do not insert records with unique fields or ID fields that already exist. Only supported by databases that support
ON CONFLICT DO NOTHING. This excludes MongoDB and SQLServer.
— Prisma Client Reference
まとめ
- seedデータには
skipDuplicates: trueを積極的に活用しよう - PostgreSQL/MySQL/MariaDBでは問題なく動作する
- SQLite/MongoDB/SQL Serverでは
skipDuplicatesは使えない
検証環境
- Prisma: v6.19.0
- 検証リポジトリ: https://github.com/hrfm1623/prisma-skipduplicates-test