StartupKitstartupkit
Database

Queries

Query patterns with Drizzle ORM

Drizzle provides two query APIs: the SQL-like query builder and the relational query API.

Basic Queries

Select all

import { ,  } from "@repo/db"

const  = await .().()

Select with columns

const  = await 
  .({
    : .id,
    : .email
  })
  .()

Where clause

import { ,  } from "@repo/db"
import { , , , ,  } from "drizzle-orm"

// Simple equality
const  = await 
  .()
  .()
  .((.email, "ian@example.com"))

// Multiple conditions
const  = await 
  .()
  .()
  .(
    (
      (.role, "admin"),
      (.emailVerified, true)
    )
  )

// Pattern matching
const  = await 
  .()
  .()
  .((.email, "%@gmail.com"))

Order and limit

const  = await 
  .()
  .()
  .((.createdAt))
  .(10)

Relational Queries

Use the relational API for nested data:

// Get user with their team memberships
const  = await ..users.findFirst({
  : (.id, ),
  : {
    : {
      : {
        : true
      }
    }
  }
})

Find many with relations

const  = await ..teams.findMany({
  : {
    : {
      : {
        : {
          : {
            : true,
            : true,
            : true
          }
        }
      }
    }
  }
})

Insert

Single insert

const [] = await 
  .()
  .({
    : .(),
    : "new@example.com",
    : "New User"
  })
  .()

Bulk insert

await .().([
  { : "1", : "First Post", :  },
  { : "2", : "Second Post", :  }
])

Insert with conflict handling

await 
  .()
  .({ , ,  })
  .({
    : .email,
    : { , : new () }
  })

Update

await 
  .()
  .({ 
    : "Updated Name",
    : new ()
  })
  .((.id, ))

Update and return

const [] = await 
  .()
  .({ : true })
  .((.id, ))
  .()

Delete

await 
  .()
  .((.userId, ))

Soft delete pattern

// Add deletedAt to schema
export const  = ("Post", {
  // ...
  : ("deletedAt", { : "date" })
})

// Soft delete
await 
  .()
  .({ : new () })
  .((.id, ))

// Query non-deleted only
const  = await 
  .()
  .()
  .((.))

Joins

Inner join

const  = await 
  .({
    : ,
    : 
  })
  .()
  .(, (.authorId, .id))

Left join

const  = await 
  .()
  .()
  .(, (.id, .authorId))

Aggregations

import { , ,  } from "@repo/db"
import { , ,  } from "drizzle-orm"

// Count
const [{  }] = await 
  .({ : () })
  .()

// Group by
const  = await 
  .({
    : .authorId,
    : ()
  })
  .()
  .(.authorId)

Transactions

await .(async () => {
  const [] = await 
    .()
    .({ : , : "New Team", : "new-team" })
    .()

  await .().({
    : .,
    : ,
    : "owner"
  })
})

Raw SQL

For complex queries:

import {  } from "@repo/db"
import {  } from "drizzle-orm"

const  = await .(`
  SELECT * FROM "User" 
  WHERE "createdAt" > NOW() - INTERVAL '7 days'
`)

Type-Safe Patterns

Query wrapper functions

import { , , type User } from "@repo/db"
import {  } from "drizzle-orm"

export async function (: string): <User | null> {
  const [] = await 
    .()
    .()
    .((.id, ))
  return  ?? null
}

export async function (: string): <User | null> {
  const [] = await 
    .()
    .()
    .((.email, ))
  return  ?? null
}

In Server Components

app/dashboard/page.tsx
import { ,  } from "@repo/db"
import {  } from "@repo/auth/server"
import {  } from "drizzle-orm"

export default async function () {
  const  = await ()
  if (!) return null

  const [] = await 
    .()
    .()
    .((.id, .user.id))

  return <>Welcome, {.name}</>
}

On this page