Prisma CRUD examples
Topics
NextjsPrisma
Published on 
21 Jan 2025
Prisma makes CRUD in Next.js simple, type-safe, and scalable. Define your schema, generate the client, and use Prisma’s API in your routes or server actions for all database operations.
prisma/schema.prisma
1generator client {
2  provider = "prisma-client-js"
3  output   = "../lib/generated/prisma"
4}
5
6datasource db {
7  provider  = "postgresql"
8  url       = env("DATABASE_URL")
9  directUrl = env("DIRECT_URL")
10}
11
12enum Role {
13  USER
14  ADMIN
15}
16
17model User {
18  id            String          @id @default(auto()) @map("_id") @db.ObjectId
19  email         String          @unique
20  name          String?
21  role          Role            @default(USER)
22  profileViews  Int             @default(0)
23  coinflips     Boolean[]
24  posts         Post[]
25  profile       ExtendedProfile?
26}
27
28model Post {
29  id        String   @id @default(auto()) @map("_id") @db.ObjectId
30  title     String
31  content   String?
32  published Boolean  @default(false)
33  author    User     @relation(fields: [authorId], references: [id])
34  authorId  String   @db.ObjectId
35}
36
37model ExtendedProfile {
38  id     String  @id @default(auto()) @map("_id") @db.ObjectId
39  bio    String?
40  user   User    @relation(fields: [userId], references: [id])
41  userId String  @unique @db.ObjectId
42}Main CRUD Operations
1// Create
2const newUser = await prisma.user.create({
3  data: {
4    email: "test@example.com",
5    name: "Test User"
6  }
7});
8
9// Read
10// Find all users
11const allUsers = await prisma.user.findMany();
12
13// Find users with at least 100 profile views who've flipped "true"
14const activeUsers = await prisma.user.findMany({
15  where: {
16    profileViews: { gte: 100 },
17    coinflips: { has: true }  // Checks array contains true
18  }
19});
20
21// Find a unique user
22const existingUser = await prisma.user.findUnique({
23  where: { email: "test@example.com" }
24});
25
26// Update
27const updatedUser = await prisma.user.update({
28  where: { id: newUser.id },
29  data: { name: "Updated Name" }
30});
31
32// Upsert (Create or Update)
33const upsertedUser = await prisma.user.upsert({
34  where: { email: "test@example.com" },
35  create: {
36    email: "test@example.com",
37    name: "New User"
38  },
39  update: {
40    profileViews: 10
41  }
42});
43
44// Delete with related posts
45const deletePosts = prisma.post.deleteMany({
46  where: { authorId: newUser.id }
47});
48
49const deleteUser = prisma.user.delete({
50  where: { id: newUser.id }
51});
52
53await prisma.$transaction([deletePosts, deleteUser]);await prisma.$transaction([deletePosts, deleteUser]) executes multiple database operations as a single atomic transaction using Prisma.
- Atomic Execution:
All operations in the array either succeed together or fail together. If any operation fails, the entire transaction is rolled back, leaving the database in its original state. - Order Matters:
Operations run sequentially in the order they appear in the array. For example: 
1// Delete posts first, THEN delete the user
2await prisma.$transaction([deletePosts, deleteUser]);If you reverse the order ([deleteUser, deletePosts]), deleting the user first would cause foreign key errors in the posts table.
Query Order: Always delete dependent records (e.g., posts) before the parent record (e.g., user).
Table of Contents