Grid
ORM

Prisma ORM Forms

Type-safe database mutations, nested relations, and error mapping with Prisma Client in Next.js.

Preview

Prisma ORM Relations

Prisma Nested Relational Form

Create deeply nested relational database records with single-transaction type safety and automated Prisma Client validation.

Nested Relation Transaction
Interactive responsive preview
Drag handles on right and bottom to resize

Overview

Prisma ORM provides an auto-generated, type-safe query builder based on your declarative schema.prisma. When paired with Next.js forms and Server Actions, Prisma simplifies complex nested inserts, atomic multi-table updates, and constraint error handling.

Schema Definition

// prisma/schema.prisma
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model Workspace {
  id        String    @id @default(cuid())
  name      String
  slug      String    @unique
  tier      String    @default("PRO")
  createdAt DateTime  @default(now())
  projects  Project[]
}

model Project {
  id          String    @id @default(cuid())
  name        String
  environment String    @default("PRODUCTION")
  workspaceId String
  workspace   Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
}

Server Action with Prisma Mutation

'use server';

import { prisma } from '@/lib/prisma';
import { Prisma } from '@prisma/client';
import { revalidatePath } from 'next/cache';
import { z } from 'zod';

const schema = z.object({
  workspaceName: z.string().min(2),
  workspaceSlug: z.string().min(2),
  initialProject: z.string().min(2),
});

export async function createWorkspace(formData: FormData) {
  const validated = schema.parse(Object.fromEntries(formData));

  try {
    const workspace = await prisma.workspace.create({
      data: {
        name: validated.workspaceName,
        slug: validated.workspaceSlug,
        projects: {
          create: [
            { name: validated.initialProject }
          ]
        }
      },
      include: {
        projects: true,
      }
    });

    revalidatePath('/workspaces');
    return { success: true, workspace };
  } catch (error) {
    if (error instanceof Prisma.PrismaClientKnownRequestError) {
      if (error.code === 'P2002') {
        return { success: false, error: 'A workspace with this slug already exists.' };
      }
    }
    return { success: false, error: 'Failed to create workspace.' };
  }
}

Best Practices

  1. Leverage Nested Writes: Use create inside relational models instead of performing multiple disjoint SQL queries.
  2. Handle Known Error Codes: Intercept PrismaClientKnownRequestError to turn constraint violations like P2002 (unique violation) into clear form error messages.
  3. Connection Pooling: Use Prisma Accelerate or Supabase/Neon connection poolers for Serverless and Edge runtimes.

On this page