Skip to main content

Column Types

SQLite uses a dynamic type system with type affinity. Drizzle provides typed column builders for common use cases.

integer()

Defines an integer column. Supports multiple modes for different data types.

Signature

function integer<TMode extends 'number' | 'timestamp' | 'timestamp_ms' | 'boolean'>(
  config?: { mode: TMode }
): SQLiteIntegerBuilder | SQLiteTimestampBuilder | SQLiteBooleanBuilder

Basic Integer

import { integer } from 'drizzle-orm/sqlite-core';

const table = sqliteTable('table', {
  id: integer('id').primaryKey({ autoIncrement: true }),
  age: integer('age').notNull(),
  score: integer('score').default(0),
});

Timestamp Mode

Stores dates as Unix timestamps (seconds since epoch).
const table = sqliteTable('table', {
  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
  updatedAt: integer('updated_at', { mode: 'timestamp' }).$onUpdate(() => new Date()),
});

// Stored as: 1703073600 (seconds)
// JavaScript: new Date()

Timestamp Milliseconds Mode

Stores dates as Unix timestamps in milliseconds.
const table = sqliteTable('table', {
  createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(),
});

// Stored as: 1703073600000 (milliseconds)
// JavaScript: new Date()

Boolean Mode

Stores booleans as integers (0 or 1).
const table = sqliteTable('table', {
  isActive: integer('is_active', { mode: 'boolean' }).notNull().default(false),
  isVerified: integer('is_verified', { mode: 'boolean' }),
});

// Stored as: 0 or 1
// JavaScript: true or false

Primary Key Options

interface PrimaryKeyConfig {
  autoIncrement?: boolean;
  onConflict?: 'rollback' | 'abort' | 'fail' | 'ignore' | 'replace';
}
id: integer('id').primaryKey({ autoIncrement: true })

text()

Defines a text column. Supports plain text, enums, and JSON.

Signature

function text<TEnum extends readonly string[], TMode extends 'text' | 'json'>(
  config?: {
    mode?: TMode;
    length?: number;
    enum?: TEnum;
  }
): SQLiteTextBuilder | SQLiteTextJsonBuilder

Basic Text

import { text } from 'drizzle-orm/sqlite-core';

const table = sqliteTable('table', {
  name: text('name').notNull(),
  description: text('description'),
  email: text('email').notNull().unique(),
});

Enum Text

Enforces type safety with predefined values.
const table = sqliteTable('table', {
  role: text('role', { enum: ['admin', 'user', 'guest'] as const }).notNull(),
  status: text('status', { enum: ['active', 'inactive', 'pending'] as const }),
});

// Type-safe: only accepts 'admin', 'user', or 'guest'
await db.insert(table).values({ role: 'admin' });

JSON Mode

Stores JSON data as text with automatic serialization.
const table = sqliteTable('table', {
  metadata: text('metadata', { mode: 'json' }),
  settings: text('settings', { mode: 'json' }).$type<{ theme: string; lang: string }>(),
});

// Automatic JSON serialization
await db.insert(table).values({
  metadata: { key: 'value' },
  settings: { theme: 'dark', lang: 'en' },
});

// Automatic JSON deserialization
const result = await db.select().from(table);
console.log(result[0].metadata.key); // 'value'

real()

Defines a real (floating-point) column.
function real(): SQLiteRealBuilder
import { real } from 'drizzle-orm/sqlite-core';

const table = sqliteTable('table', {
  price: real('price').notNull(),
  rating: real('rating').default(0.0),
  latitude: real('latitude'),
  longitude: real('longitude'),
});

numeric()

Defines a numeric column. Useful for precise decimal values.

Signature

function numeric<TMode extends 'string' | 'number' | 'bigint'>(
  config?: { mode: TMode }
): SQLiteNumericBuilder | SQLiteNumericNumberBuilder | SQLiteNumericBigIntBuilder

String Mode (Default)

Preserves precision as string.
const table = sqliteTable('table', {
  amount: numeric('amount'),
  balance: numeric('balance').notNull(),
});

// Stored and retrieved as string
// JavaScript: '123.45'

Number Mode

Converts to JavaScript number.
const table = sqliteTable('table', {
  price: numeric('price', { mode: 'number' }),
});

// JavaScript: 123.45

BigInt Mode

Converts to JavaScript bigint.
const table = sqliteTable('table', {
  largeValue: numeric('large_value', { mode: 'bigint' }),
});

// JavaScript: 123n

blob()

Defines a blob (binary) column. Supports buffer, JSON, and bigint modes.

Signature

function blob<TMode extends 'buffer' | 'json' | 'bigint'>(
  config?: { mode: TMode }
): SQLiteBlobBufferBuilder | SQLiteBlobJsonBuilder | SQLiteBigIntBuilder

Buffer Mode (Default)

Stores binary data.
import { blob } from 'drizzle-orm/sqlite-core';

const table = sqliteTable('table', {
  avatar: blob('avatar', { mode: 'buffer' }),
  file: blob('file', { mode: 'buffer' }).notNull(),
});

// JavaScript: Buffer
await db.insert(table).values({
  avatar: Buffer.from('binary data'),
});

JSON Mode

Stores JSON as binary. Note: Use text('...', { mode: 'json' }) instead for JSON functions support.
const table = sqliteTable('table', {
  data: blob('data', { mode: 'json' }),
});

// Automatic JSON serialization to binary
await db.insert(table).values({
  data: { key: 'value' },
});
SQLite’s JSON functions don’t work with blob columns. Use text('...', { mode: 'json' }) if you need JSON functions.

BigInt Mode

Stores bigint values as binary.
const table = sqliteTable('table', {
  largeNumber: blob('large_number', { mode: 'bigint' }),
});

// JavaScript: bigint
await db.insert(table).values({
  largeNumber: 12345678901234567890n,
});

Column Modifiers

All column builders support these chainable methods:

notNull()

Makes the column non-nullable.
name: text('name').notNull()

default()

Sets a default value.
createdAt: integer('created_at', { mode: 'timestamp' })
  .notNull()
  .default(sql`(unixepoch())`)

primaryKey()

Marks the column as the primary key.
id: integer('id').primaryKey({ autoIncrement: true })

unique()

Adds a unique constraint.
email: text('email').notNull().unique()

references()

Defines a foreign key reference.
userId: integer('user_id')
  .notNull()
  .references(() => users.id, { onDelete: 'cascade' })

$type()

Overrides the TypeScript type.
metadata: text('metadata', { mode: 'json' })
  .$type<{ version: number; flags: string[] }>()

$default()

Sets a runtime default value function.
id: text('id').$default(() => crypto.randomUUID())

$onUpdate()

Sets a function to run on every update.
updatedAt: integer('updated_at', { mode: 'timestamp' })
  .$onUpdate(() => new Date())

$onUpdateFn()

Sets a SQL expression to run on update.
updatedAt: integer('updated_at', { mode: 'timestamp' })
  .$onUpdateFn(() => sql`(unixepoch())`)

Generated Columns

SQLite supports generated columns (virtual and stored).
const table = sqliteTable('table', {
  price: real('price').notNull(),
  quantity: integer('quantity').notNull(),
  total: real('total').generatedAlwaysAs(
    sql`${price} * ${quantity}`,
    { mode: 'virtual' }
  ),
});

Type Inference

Drizzle automatically infers TypeScript types from column definitions:
const users = sqliteTable('users', {
  id: integer('id').primaryKey({ autoIncrement: true }),
  name: text('name').notNull(),
  email: text('email').notNull(),
  role: text('role', { enum: ['admin', 'user'] as const }).notNull(),
  isActive: integer('is_active', { mode: 'boolean' }).default(true),
  createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
});

// Inferred types:
type User = typeof users.$inferSelect;
// {
//   id: number;
//   name: string;
//   email: string;
//   role: 'admin' | 'user';
//   isActive: boolean | null;
//   createdAt: Date;
// }

type NewUser = typeof users.$inferInsert;
// {
//   id?: number;
//   name: string;
//   email: string;
//   role: 'admin' | 'user';
//   isActive?: boolean | null;
//   createdAt: Date;
// }

Build docs developers (and LLMs) love