PostgreSQL column types
We have native support for all of them, yet if that's not enough for you - feel free to create custom types.
integer
integer
int
int4
Signed 4-byte integer
If you need integer autoincrement
- please refer to serial
import { integer, pgTable } from "drizzle-orm/pg-core";
export const table = pgTable('table', {
int: integer('int')
});
CREATE TABLE IF NOT EXISTS "table" (
"int" integer
);
import { sql } from "drizzle-orm";
import { integer, pgTable } from "drizzle-orm/pg-core";
export const table = pgTable('table', {
int1: integer('int1').default(10)
int2: integer('int2').default(sql`'10'::int`)
});
CREATE TABLE IF NOT EXISTS "table" (
"int1" integer DEFAULT 10
"int2" integer DEFAULT '10'::int
);
smallint
smallint
int2
Small-range signed 2-byte integer
If you need smallint autoincrement
- please refer to smallserial
import { smallint, pgTable } from "drizzle-orm/pg-core";
export const table = pgTable('table', {
smallint: smallint('smallint')
});
CREATE TABLE IF NOT EXISTS "table" (
"smallint" smallint
);
import { sql } from "drizzle-orm";
import { smallint, pgTable } from "drizzle-orm/pg-core";
export const table = pgTable('table', {
smallint1: smallint('smallint1').default(10)
smallint2: smallint('smallint2').default(sql`'10'::smallint`)
});
CREATE TABLE IF NOT EXISTS "table" (
"smallint1" smallint DEFAULT 10
"smallint2" smallint DEFAULT '10'::smallint
);
bigint
bigint
int8
Signed 8-byte integer
If you need bigint autoincrement
- please refer to bigserial
If you're expecting values above 2^31 but below 2^53, you can utilise mode: 'number'
and deal with javascript number as opposed to bigint
import { bigint, pgTable } from "drizzle-orm/pg-core";
export const table = pgTable('table', {
bigint: bigint('bigint', { mode: 'number' })
});
// will be inferred as `number`
bigint: bigint('bigint', { mode: 'number' })
// will be inferred as `bigint`
bigint: bigint('bigint', { mode: 'bigint' })
CREATE TABLE IF NOT EXISTS "table" (
"bigint" bigint
);
import { sql } from "drizzle-orm";
import { bigint, pgTable } from "drizzle-orm/pg-core";
export const table = pgTable('table', {
bigint1: bigint('bigint1').default(10)
bigint2: bigint('bigint2').default(sql`'10'::bigint`)
});
CREATE TABLE IF NOT EXISTS "table" (
"bigint1" bigint DEFAULT 10
"bigint2" bigint DEFAULT '10'::bigint
);
serial
serial
serial4
Auto incrementing 4-bytes integer, notational convenience for creating unique identifier columns (similar to the AUTO_INCREMENT
property supported by some other databases).
Official PostrgreSQL docs (opens in a new tab)
import { serial, pgTable } from "drizzle-orm/pg-core";
export const table = pgTable('table', {
serial: serial('serial'),
});
CREATE TABLE IF NOT EXISTS "table" (
"serial" serial NOT NULL,
);
smallserial
smallserial
serial2
Auto incrementing 2-bytes integer, notational convenience for creating unique identifier columns (similar to the AUTO_INCREMENT
property supported by some other databases).
Official PostrgreSQL docs (opens in a new tab)
import { smallserial, pgTable } from "drizzle-orm/pg-core";
export const table = pgTable('table', {
smallserial: smallserial('smallserial'),
});
CREATE TABLE IF NOT EXISTS "table" (
"smallserial" smallserial NOT NULL,
);
bigserial
bigserial
serial8
Auto incrementing 8-bytes integer, notational convenience for creating unique identifier columns (similar to the AUTO_INCREMENT
property supported by some other databases).
Official PostrgreSQL docs (opens in a new tab)
If you're expecting values above 2^31 but below 2^53, you can utilise mode: 'number'
and deal with javascript number as opposed to bigint
import { bigserial, pgTable } from "drizzle-orm/pg-core";
export const table = pgTable('table', {
bigserial: bigserial('bigserial', { mode: 'number' }),
});
CREATE TABLE IF NOT EXISTS "table" (
"bigserial" bigserial NOT NULL,
);
boolean
PostgreSQL provides the standard SQL type boolean Official PostrgreSQL docs (opens in a new tab)
import { boolean, pgTable } from "drizzle-orm/pg-core";
export const table = pgTable('table', {
boolean: boolean('boolean')
});
CREATE TABLE IF NOT EXISTS "table" (
"boolean" boolean,
);
text
text
Variable-length(unlimited) character string
Official PostrgreSQL docs (opens in a new tab)
You can define { enum: ["value1", "value2"] }
config to infer insert
and select
types, it won't check runtime values
import { text, pgTable } from "drizzle-orm/pg-core";
export const table = pgTable('table', {
text: text('text')
});
// will be inferred as text: "value1" | "value2" | null
text: text('text', { enum: ["value1", "value2"] })
CREATE TABLE IF NOT EXISTS "table" (
"text" text,
);
varchar
character varying(n)
varchar(n)
Variable-length character string, can store strings up to n
characters(not bytes)
Official PostrgreSQL docs (opens in a new tab)
You can define { enum: ["value1", "value2"] }
config to infer insert
and select
types, it won't check runtime values
length
parameter is optional according to PostgreSQL docs
import { varchar, pgTable } from "drizzle-orm/pg-core";
export const table = pgTable('table', {
varchar1: varchar('varchar1'),
varchar1: varchar('varchar2', { length: 256 }),
});
// will be inferred as text: "value1" | "value2" | null
varchar: varchar('varchar', { enum: ["value1", "value2"] }),
CREATE TABLE IF NOT EXISTS "table" (
"varchar1" varchar,
"varchar2" varchar(256),
);
char
character(n)
char(n)
Fixed-length, blank padded character string, can store strings up to n
characters(not bytes)
Official PostrgreSQL docs (opens in a new tab)
You can define { enum: ["value1", "value2"] }
config to infer insert
and select
types, it won't check runtime values
length
parameter is optional according to PostgreSQL docs
import { char, pgTable } from "drizzle-orm/pg-core";
export const table = pgTable('table', {
char1: char('char1'),
char2: char('char2', { length: 256 }),
});
// will be inferred as text: "value1" | "value2" | null
char: char('char', { enum: ["value1", "value2"] }),
CREATE TABLE IF NOT EXISTS "table" (
"char1" char,
"char2" char(256),
);
numeric
numeric
decimal
Exact numeric of selectable precision. Can store numbers with a very large number of digits, up to 131072 digits before the decimal point and up to 16383 digits after the decimal point
Official PostrgreSQL docs (opens in a new tab)
import { numeric, pgTable } from "drizzle-orm/pg-core";
export const table = pgTable('table', {
numeric1: numeric('numeric1'),
numeric2: numeric('numeric2', { precision: 100 }),
numeric3: numeric('numeric3', { precision: 100, scale: 20 }),
});
CREATE TABLE IF NOT EXISTS "table" (
"numeric1" numeric,
"numeric2" numeric(100),
"numeric3" numeric(100, 20),
);
decimal
Is an alias of numeric
real
real
float4
Single precision floating-point number (4 bytes)
Official PostrgreSQL docs (opens in a new tab)
import { sql } from "drizzle-orm";
import { real, pgTable } from "drizzle-orm/pg-core";
const table = pgTable('table', {
real1: real('real1'),
real2: real('real2').default(10.10),
real2: real('real2').default(sql`'10.10'::real`),
});
CREATE TABLE IF NOT EXISTS "table" (
"real1" real,
"real2" real default 10.10,
"real2" real default '10.10'::real
);
double precision
double precision
float8
Double precision floating-point number (8 bytes)
Official PostrgreSQL docs (opens in a new tab)
import { sql } from "drizzle-orm";
import { doublePrecision, pgTable } from "drizzle-orm/pg-core";
const table = pgTable('table', {
double1: doublePrecision('double1'),
double2: doublePrecision('double2').default(10.10),
double3: doublePrecision('double3').default(sql`'10.10'::double precision`),
});
CREATE TABLE IF NOT EXISTS "table" (
"double1" double precision,
"double2" double precision default 10.10,
"double3" double precision default '10.10'::double precision,
);
json
json
Textual JSON data, as specified in RFC 7159 (opens in a new tab)
Official PostrgreSQL docs (opens in a new tab)
import { sql } from "drizzle-orm";
import { json, pgTable } from "drizzle-orm/pg-core";
const table = pgTable('table', {
json1: json('json1'),
json2: json('json2').default({ foo: "bar" }),
json3: json('json3').default(sql`'{foo: "bar"}'::json`),
});
CREATE TABLE IF NOT EXISTS "table" (
"json1" json,
"json2" json default '{"foo": "bar"}'::json,
"json3" json default '{"foo": "bar"}'::json,
);
You can specify .$type<..>()
for json object inference, it won't check runtime values.
It provides compile time protection for default values, insert and select schemas.
// will be infered as { foo: string }
json: json('json').$type<{ foo: string }>();
// will be infered as string[]
json: json('json').$type<string[]>();
// won't compile
json: json('json').$type<string[]>().default({});
jsonb
jsonb
Binary JSON data, decomposed
Official PostrgreSQL docs (opens in a new tab)
import { jsonb, pgTable } from "drizzle-orm/pg-core";
const table = pgTable('table', {
jsonb1: jsonb('jsonb1'),
jsonb2: jsonb('jsonb2').default({ foo: "bar" }),
jsonb3: jsonb('jsonb3').default(sql`'{foo: "bar"}'::jsonb`),
});
CREATE TABLE IF NOT EXISTS "table" (
"jsonb1" jsonb,
"jsonb2" jsonb default '{"foo": "bar"}'::jsonb,
"jsonb3" jsonb default '{"foo": "bar"}'::jsonb,
);
You can specify .$type<..>()
for json object inference, it won't check runtime values.
It provides compile time protection for default values, insert and select schemas.
// will be infered as { foo: string }
jsonb: jsonb('jsonb').$type<{ foo: string }>();
// will be infered as string[]
jsonb: jsonb('jsonb').$type<string[]>();
// won't compile
jsonb: jsonb('jsonb').$type<string[]>().default({});
time
time
timetz
time with timezone
time without timezone
Time of day with or without time zone
PostgreSQL docs (opens in a new tab)
import { time, pgTable } from "drizzle-orm/pg-core";
const table = pgTable('table', {
time1: time('time1'),
time2: time('time2', { withTimezone: true }),
time3: time('time3', { precision: 6 }),
time4: time('time4', { precision: 6, withTimezone: true })
});
CREATE TABLE IF NOT EXISTS "table" (
"time1" time,
"time2" time with timezone,
"time3" time(6),
"time4" time(6) with timezone,
);
timestamp
timestamp
timestamptz
timestamp with time zone
timestamp without time zone
Date and time with or without time zone
PostgreSQL docs (opens in a new tab)
import { sql } from "drizzle-orm";
import { timestamp, pgTable } from "drizzle-orm/pg-core";
const table = pgTable('table', {
timestamp1: timestamp('timestamp1'),
timestamp2: timestamp('timestamp2', { precision: 6, withTimezone: true }),
timestamp3: timestamp('timestamp3').defaultNow(),
timestamp4: timestamp('timestamp4').default(sql`now()`),
});
CREATE TABLE IF NOT EXISTS "table" (
"timestamp1" timestamp,
"timestamp2" timestamp (6) with time zone,
"timestamp3" timestamp default now(),
"timestamp4" timestamp default now(),
);
You can specify either date
or string
infer modes
// will infer as date
timestamp: timestamp('timestamp', { mode: "date" }),
// will infer as string
timestamp: timestamp('timestamp', { mode: "string" }),
date
date
Calendar date (year, month, day)
PostgreSQL docs (opens in a new tab)
import { date, pgTable } from "drizzle-orm/pg-core";
const table = pgTable('table', {
date: date('date'),
});
CREATE TABLE IF NOT EXISTS "table" (
"date" date,
);
You can specify either date
or string
infer modes
// will infer as date
date: date('date', { mode: "date" }),
// will infer as string
date: date('date', { mode: "string" }),
interval
interval
Time span
PostgreSQL docs (opens in a new tab)
import { interval, pgTable } from "drizzle-orm/pg-core";
const table = pgTable('table', {
interval1: interval('interval1'),
interval2: interval('interval2', { fields: 'day' }),
interval3: interval('interval3', { fields: 'month' , precision: 6 }),
});
CREATE TABLE IF NOT EXISTS "table" (
"interval1" interval,
"interval2" interval day,
"interval3" interval(6) month,
);
enum
enum
enumerated types
Enumerated (enum) types are data types that comprise a static, ordered set of values.
They are equivalent to the enum types supported in a number of programming languages.
An example of an enum type might be the days of the week, or a set of status values for a piece of data.
PostgreSQL docs (opens in a new tab)
import { pgEnum, pgTable } from "drizzle-orm/pg-core";
const moodEnum = pgEnum('mood', ['sad', 'ok', 'happy']);
const table = pgTable('table', {
mood: moodEnum('mood'),
});
CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');
CREATE TABLE IF NOT EXISTS "table" (
"mood" mood,
);
Constraints & defaults
Default value
The DEFAULT
clause specifies a default value to use for the column if no value
is explicitly provided by the user when doing an INSERT
.
If there is no explicit DEFAULT
clause attached to a column definition,
then the default value of the column is NULL
.
An explicit DEFAULT
clause may specify that the default value is NULL
,
a string constant, a blob constant, a signed-number, or any constant expression enclosed in parentheses.
import { sql } from "drizzle-orm";
import { integer, pgTable, uuid } from "drizzle-orm/pg-core";
const table = pgTable('table', {
integer1: integer('integer1').default(42),
integer2: integer('integer2').default(sql`'42'::integer`),
uuid1: uuid('uuid1').defaultRandom(),
uuid2: uuid('uuid2').default(sql`get_random_uuid()`),
});
CREATE TABLE IF NOT EXISTS "table" (
"integer1" integer DEFAULT 42,
"integer2" integer DEFAULT '42'::integer,
"uuid1" uuid DEFAULT gen_random_uuid(),
"uuid2" uuid DEFAULT gen_random_uuid()
);
Not null
NOT NULL
constraint dictates that the associated column may not contain a NULL
value
import { integer, pgTable } from "drizzle-orm/pg-core";
const table = pgTable('table', {
integer: integer('integer').notNull(),
});
CREATE TABLE IF NOT EXISTS "table" (
"integer" integer NOT NULL,
);
Primary key
A primary key constraint indicates that a column, or group of columns, can be used as a unique identifier for rows in the table. This requires that the values be both unique and not null.
import { integer, pgTable } from "drizzle-orm/pg-core";
const table = pgTable('table', {
id: serial('id').primaryKey(),
});
CREATE TABLE IF NOT EXISTS "table" (
"integer" serial PRIMARY KEY NOT NULL,
);