Working with Unique Constraints

1. Creating Single Field Unique

email String @unique
AspectDetail
IndexUnique B-tree
LookupUsable in findUnique

2. Defining Composite Unique

@@unique([provider, providerAccountId])
PatternUse
OAuth accounts(provider, providerAccountId)
Memberships(userId, orgId)

3. Using Unique in findUnique

await prisma.account.findUnique({
  where: { provider_providerAccountId: { provider: "github", providerAccountId: "42" } }
});
AspectDetail
Compound keyAuto-named or via name
Custom name@@unique([..], name: "providerKey")

4. Handling Unique Violations

CodeDetail
P2002e.meta.target lists offending fields
RecoverConvert to upsert or surface 409

5. Creating Conditional Unique Constraints

DBApproach
PGPartial index via raw SQL: CREATE UNIQUE INDEX ... WHERE deletedAt IS NULL
MySQLFiltered uniqueness emulated via expression columns

6. Using Case-Insensitive Unique

DBApproach
PGString @db.Citext @unique
MySQLUse utf8mb4_0900_ai_ci collation

7. Implementing Partial Unique Indexes

Use CaseDetail
Soft deleteUnique only when not deleted
Active flagUnique only for active rows
ImplementationRaw SQL in migration

8. Updating Unique Fields

RiskMitigation
CollisionWrap in try/catch for P2002
RaceUse transaction with serializable isolation

9. Deleting by Unique Fields

await prisma.user.delete({ where: { email: "a@b.io" } });
AspectDetail
ConstraintMust be unique field
CompositeUse compound shape

10. Validating Uniqueness at Runtime

ApproachDetail
Pre-check + insertVulnerable to race conditions
Try insert + handle P2002Recommended pattern
UpsertRace-safe for idempotent ops