Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/drizzle-team/drizzle-orm/llms.txt

Use this file to discover all available pages before exploring further.

Drizzle ORM provides a powerful and type-safe query builder for selecting data from your database. The select query builder supports a wide range of operations including filtering, joining, grouping, and ordering.

Basic Select

Select all columns from a table:
import { db } from './db';
import { users } from './schema';

// Select all columns from users
const allUsers = await db.select().from(users);

Partial Select

Select specific columns from a table:
// Select only id and name
const userNames = await db.select({
  id: users.id,
  name: users.name,
}).from(users);

Filtering with Where

Use the where() method to filter results:
import { eq, gt, lt } from 'drizzle-orm';

// Select users with a specific id
const user = await db.select()
  .from(users)
  .where(eq(users.id, 1));

// Select users older than 18
const adults = await db.select()
  .from(users)
  .where(gt(users.age, 18));

Ordering Results

Use orderBy() to sort query results:
import { asc, desc } from 'drizzle-orm';

// Order by name ascending
const users = await db.select()
  .from(users)
  .orderBy(asc(users.name));

// Order by created date descending
const recentUsers = await db.select()
  .from(users)
  .orderBy(desc(users.createdAt));

// Multiple order by clauses
const sortedUsers = await db.select()
  .from(users)
  .orderBy(asc(users.role), desc(users.createdAt));

Limiting and Offsetting

Control the number of results returned:
// Get first 10 users
const firstTen = await db.select()
  .from(users)
  .limit(10);

// Pagination: skip first 20, get next 10
const page3 = await db.select()
  .from(users)
  .limit(10)
  .offset(20);

Distinct

Select only distinct values:
// Get unique user roles
const roles = await db.selectDistinct({ role: users.role })
  .from(users);

Group By

Group results by one or more columns:
import { count } from 'drizzle-orm';

// Count users by role
const usersByRole = await db.select({
  role: users.role,
  count: count(),
})
  .from(users)
  .groupBy(users.role);

Having Clause

Filter grouped results:
import { count, gt } from 'drizzle-orm';

// Get roles with more than 5 users
const popularRoles = await db.select({
  role: users.role,
  count: count(),
})
  .from(users)
  .groupBy(users.role)
  .having(({ count }) => gt(count, 5));

Set Operations

Combine multiple select queries:
// Combine results and remove duplicates
const combined = await db.select({ name: users.name })
  .from(users)
  .union(
    db.select({ name: customers.name }).from(customers)
  );

Conditional Where

Build dynamic queries with conditional logic:
const filters = {
  role: 'admin',
  minAge: 18,
};

const conditions = [];
if (filters.role) {
  conditions.push(eq(users.role, filters.role));
}
if (filters.minAge) {
  conditions.push(gt(users.age, filters.minAge));
}

const result = await db.select()
  .from(users)
  .where(and(...conditions));

With Clause (CTE)

Use Common Table Expressions:
const activeUsers = db.$with('active_users').as(
  db.select().from(users).where(eq(users.active, true))
);

const result = await db.with(activeUsers)
  .select()
  .from(activeUsers);

For Update (PostgreSQL)

Lock rows for update:
// Lock selected rows
const user = await db.select()
  .from(users)
  .where(eq(users.id, 1))
  .for('update');

// Lock with NOWAIT
const user = await db.select()
  .from(users)
  .where(eq(users.id, 1))
  .for('update', { noWait: true });

// Lock specific tables
const result = await db.select()
  .from(users)
  .leftJoin(posts, eq(users.id, posts.userId))
  .for('update', { of: users });

Conditional Operators Reference

Comparison

  • eq() - Equal to
  • ne() - Not equal to
  • gt() - Greater than
  • gte() - Greater than or equal
  • lt() - Less than
  • lte() - Less than or equal

Logical

  • and() - Combine with AND
  • or() - Combine with OR
  • not() - Negate condition

Patterns

  • like() - Pattern matching
  • ilike() - Case-insensitive pattern
  • notLike() - Not matching pattern
  • notIlike() - Case-insensitive not matching

Ranges & Sets

  • between() - Between two values
  • notBetween() - Not between values
  • inArray() - In array of values
  • notInArray() - Not in array

Null Checks

  • isNull() - Is NULL
  • isNotNull() - Is NOT NULL

Subqueries

  • exists() - Subquery has results
  • notExists() - Subquery has no results

Type Safety

Drizzle ensures complete type safety:
// TypeScript knows the exact shape of the result
const users = await db.select({
  id: users.id,
  name: users.name,
}).from(users);

// users is typed as: { id: number; name: string; }[]
All query methods are fully typed, providing autocomplete and compile-time type checking.

Next Steps

Joins

Learn about joining tables together

Aggregations

Use aggregate functions like count, sum, avg

Subqueries

Write complex nested queries

Insert

Insert data into tables