PostgreSQL 列类型

我们原生支持所有这些类型,但如果这还不够,你可以随意创建 自定义类型

integer

integer int int4
有符号的 4 字节整数

如果你需要 integer autoincrement 请参考 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
小范围有符号的 2 字节整数

如果你需要 smallint autoincrement 请参考 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
有符号的 8 字节整数

如果你需要 bigint autoincrement 请参考 bigserial

如果你预期的值在 2^31 以上但低于 2^53,你可以使用 mode: 'number' 并处理 javascript 数字而不是 bigint。

import { bigint, pgTable } from "drizzle-orm/pg-core";

export const table = pgTable('table', {
  bigint: bigint('bigint', { mode: 'number' })
});

// 将被推断为 `number`
bigint: bigint('bigint', { mode: 'number' })

// 将被推断为 `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
自动递增的 4 字节整数,创建唯一标识列的简便表示(类似于其他一些数据库支持的 AUTO_INCREMENT 属性)。

有关更多信息,请参考官方 PostgreSQL 文档.

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
自动递增的 2 字节整数,创建唯一标识列的简便表示(类似于其他一些数据库支持的 AUTO_INCREMENT 属性)。

有关更多信息,请参考官方 PostgreSQL 文档.

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
自动递增的 8 字节整数,创建唯一标识列的简便表示(类似于其他一些数据库支持的 AUTO_INCREMENT 属性)。

有关更多信息,请参考官方 PostgreSQL 文档.

如果你预期的值在 2^31 以上但低于 2^53,你可以使用 mode: 'number' 并处理 javascript 数字而不是 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 提供了标准的 SQL 类型 boolean。

有关更多信息,请参考官方 PostgreSQL 文档.

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
可变长度(无限制)的字符字符串。

有关更多信息,请参考官方 PostgreSQL 文档.

你可以定义 { enum: ["value1", "value2"] } 配置来推断 insertselect 类型,它 不会 检查运行时值。

import { text, pgTable } from "drizzle-orm/pg-core";

export const table = pgTable('table', {
  text: text('text')
});

// 将被推断为 text: "value1" | "value2" | null
text: text('text', { enum: ["value1", "value2"] })
CREATE TABLE IF NOT EXISTS "table" (
  "text" text,
);

varchar

character varying(n) varchar(n)
可变长度的字符字符串,可以存储最多 n 个字符(不是字节)。

有关更多信息,请参考官方 PostgreSQL 文档.

你可以定义 { enum: ["value1", "value2"] } 配置来推断 insertselect 类型,它 不会 检查运行时值。

length 参数根据 PostgreSQL 文档是可选的。

import { varchar, pgTable } from "drizzle-orm/pg-core";

export const table = pgTable('table', {
  varchar1: varchar('varchar1'),
  varchar2: varchar('varchar2', { length: 256 }),
});

// 将被推断为 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)
固定长度,空白填充的字符字符串,可以存储多达 n 个字符(不是字节)。

有关更多信息,请参考官方 PostgreSQL 文档。

您可以定义 { enum: ["value1", "value2"] } 配置来推断 insertselect 类型,它 不会 检查运行时值。

根据 PostgreSQL 文档,length 参数是可选的。

import { char, pgTable } from "drizzle-orm/pg-core";

export const table = pgTable('table', {
  char1: char('char1'),
  char2: char('char2', { length: 256 }),
});

// 将被推断为 text: "value1" | "value2" | null
char: char('char', { enum: ["value1", "value2"] }),
CREATE TABLE IF NOT EXISTS "table" (
  "char1" char,
  "char2" char(256),
);

numeric

numeric decimal
可选定精度的精确数值。可以存储多达 131072 个数字的数字,小数点前多达 131072 个数字,小数点后多达 16383 个数字。

有关更多信息,请参考官方 PostgreSQL 文档。

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

numeric. 的别名

real

real float4
单精度浮点数(4 字节)

有关更多信息,请参考官方 PostgreSQL 文档。

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
双精度浮点数(8 字节)

有关更多信息,请参考官方 PostgreSQL 文档。

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
文本 JSON 数据,如 RFC 7159. 所指定的。

有关更多信息,请参考官方 PostgreSQL 文档。

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,
);

您可以指定 .$type<..>() 用于 json 对象推断,它 不会 检查运行时值。 它为默认值、插入和选择模式提供编译时保护。

// 将被推断为 { foo: string }
json: json('json').$type<{ foo: string }>();

// 将被推断为 string[]
json: json('json').$type<string[]>();

// 不会编译
json: json('json').$type<string[]>().default({});

jsonb

jsonb
二进制 JSON 数据,已分解。

有关更多信息,请参考官方 PostgreSQL 文档。

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,
);

您可以指定 .$type<..>() 用于 json 对象推断,它 不会 检查运行时值。 它为默认值、插入和选择模式提供编译时保护。

// 将被推断为 { foo: string }
jsonb: jsonb('jsonb').$type<{ foo: string }>();

// 将被推断为 string[]
jsonb: jsonb('jsonb').$type<string[]>();

// 不会编译
jsonb: jsonb('jsonb').$type<string[]>().default({});

time

time timetz time with timezone time without timezone
带或不带时区的时间。

有关更多信息,请参考官方 PostgreSQL 文档。

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
日期和时间,带或不带时区。

有关更多信息,请参考官方 PostgreSQL 文档。

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(),
);

您可以指定 datestring 推断模式:

// 将推断为 date
timestamp: timestamp('timestamp', { mode: "date" }),

// 将推断为 string
timestamp: timestamp('timestamp', { mode: "string" }),

string 模式不会为您执行任何映射。这种模式被添加到 Drizzle ORM 中是为了提供给开发者根据他们的需求自己处理日期和日期映射的可能性。 Drizzle 将原始日期作为字符串 tofrom 数据库传递,因此行为应该尽可能可预测,并且与数据库行为 100% 对齐

date 模式是处理日期的常规方式。Drizzle 将负责数据库和 JS Date 对象之间的所有映射

ℹ️

timestamptimestamp with timezone 的映射工作原理:

正如 PostgreSQL 文档所述:

在已确定为不带时区的时间戳的字面量中,PostgreSQL 将静默忽略任何时区指示。 也就是说,结果值来源于输入值中的日期/时间字段,并不会根据时区进行调整。

对于带有时区的时间戳,内部存储的值总是在 UTC(协调世界时,传统上称为格林威治标准时间,GMT)中。 输入值如果指定了明确的时区,则会使用该时区的适当偏移量转换为 UTC。 如果输入字符串中没有声明时区,则假定其处于系统 TimeZone 参数指示的时区,并使用该时区区域的偏移量转换为 UTC。

因此,对于 timestamp with timezone 您将得到转换为您的 Postgres 实例中设置的时区的字符串。 您可以使用此 SQL 查询检查时区:

show timezone;

date

date
日历日期(年,月,日)

有关更多信息,请参考官方 PostgreSQL 文档。

import { date, pgTable } from "drizzle-orm/pg-core";

const table = pgTable('table', {
  date: date('date'),
});
CREATE TABLE IF NOT EXISTS "table" (
  "date" date,
);

您可以指定 datestring 推断模式:

// 将推断为 date
date: date('date', { mode: "date" }),

// 将推断为 string
date: date('date', { mode: "string" }),

interval

interval
时间跨度

有关更多信息,请参考官方 PostgreSQL 文档。

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,
);

point

point
Geometric point type

For more info please refer to the official PostgreSQL docs.

Type point has 2 modes for mappings from the database: tuple and xy.

  • tuple will be accepted for insert and mapped on select to a tuple. So, the database Point(1,2) will be typed as [1,2] with drizzle.

  • xy will be accepted for insert and mapped on select to an object with x, y coordinates. So, the database Point(1,2) will be typed as { x: 1, y: 2 } with drizzle

const items = pgTable('items', {
 point: point('point'),
 pointObj: point('point_xy', { mode: 'xy' }),
});
CREATE TABLE IF NOT EXISTS "items" (
  "point" point,
  "point_xy" point,
);

line

line
Geometric line type

For more info please refer to the official PostgreSQL docs.

Type line has 2 modes for mappings from the database: tuple and abc.

  • tuple will be accepted for insert and mapped on select to a tuple. So, the database Line3 will be typed as [1,2,3] with drizzle.

  • abc will be accepted for insert and mapped on select to an object with a, b, and c constants from the equation Ax + By + C = 0. So, the database Line3 will be typed as { a: 1, b: 2, c: 3 } with drizzle.

const items = pgTable('items', {
 line: line('line'),
 lineObj: point('line_abc', { mode: 'abc' }),
});
CREATE TABLE IF NOT EXISTS "items" (
  "line" line,
  "line_abc" line,
);

enum

enum enumerated types
枚举(enum)类型是由一组静态有序值组成的数据类型。 它们等同于许多编程语言中支持的枚举类型。 枚举类型的例子可能是一周的天数,或者是数据状态值的一组。

有关更多信息,请参考官方 PostgreSQL 文档。

import { pgEnum, pgTable } from "drizzle-orm/pg-core";

export const moodEnum = pgEnum('mood', ['sad', 'ok', 'happy']);

export const table = pgTable('table', {
  mood: moodEnum('mood'),
});
CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');

CREATE TABLE IF NOT EXISTS "table" (
  "mood" mood,
);

自定义列数据类型

每个列构建器都有一个 .$type() 方法,它允许您自定义列的数据类型。

这在处理未知或品牌类型时非常有用:

type UserId = number & { __brand: 'user_id' };
type Data = {
  foo: string;
  bar: number;
};

const users = pgTable('users', {
  id: serial('id').$type<UserId>().primaryKey(),
  jsonField: json('json_field').$type<Data>(),
});

约束和默认值

Identity Columns

💡

To use this feature you would need to have drizzle-orm@0.32.0 or higher and drizzle-kit@0.23.0 or higher

PostgreSQL supports identity columns as a way to automatically generate unique integer values for a column. These values are generated using sequences and can be defined using the GENERATED AS IDENTITY clause.

Types of Identity Columns

  • GENERATED ALWAYS AS IDENTITY: The database always generates a value for the column. Manual insertion or updates to this column are not allowed unless the OVERRIDING SYSTEM VALUE clause is used.
  • GENERATED BY DEFAULT AS IDENTITY: The database generates a value by default, but manual values can also be inserted or updated. If a manual value is provided, it will be used instead of the system-generated value.

Key Features

  • Automatic Value Generation: Utilizes sequences to generate unique values for each new row.
  • Customizable Sequence Options: You can define starting values, increments, and other sequence options.
  • Support for Multiple Identity Columns: PostgreSQL allows more than one identity column per table.

Limitations

  • Manual Insertion Restrictions: For columns defined with GENERATED ALWAYS AS IDENTITY, manual insertion or updates require the OVERRIDING SYSTEM VALUE clause.
  • Sequence Constraints: Identity columns depend on sequences, which must be managed correctly to avoid conflicts or gaps.

Usage example

import { pgTable, integer, text } from 'drizzle-orm/pg-core' 

export const ingredients = pgTable("ingredients", {
  id: integer("id").primaryKey().generatedAlwaysAsIdentity({ startWith: 1000 }),
  name: text("name").notNull(),
  description: text("description"),
});

You can specify all properties available for sequences in the .generatedAlwaysAsIdentity() function. Additionally, you can specify custom names for these sequences

PostgreSQL docs reference.

默认值

DEFAULT 子句指定了如果在执行 INSERT 时用户没有显式提供值,则用于列的默认值。 如果没有附加到列定义的显式 DEFAULT 子句, 那么列的默认值就是 NULL

显式的 DEFAULT 子句可以指定默认值为 NULL, 一个字符串常量,一个 blob 常量,一个带符号的数字,或任何用括号括起来的常量表达式。

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`gen_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()
);

当使用 $default()$defaultFn(),这只是相同功能的两个不同别名时, 您可以在运行时生成默认值,并在所有插入查询中使用这些值。

这些函数可以帮助您使用各种实现,如 uuidcuidcuid2 等。

ℹ️

注意:这个值不会影响 drizzle-kit 的行为,它只在 drizzle-orm 中的运行时使用

import { text, pgTable } from "drizzle-orm/pg-core";
import { createId } from '@paralleldrive/cuid2';

const table = pgTable('table', {
  id: text('id').$defaultFn(() => createId()),
});

当使用 $onUpdate()$onUpdateFn(),这只是相同功能的两个不同别名时, 您可以在运行时生成默认值,并在所有更新查询中使用这些值。

为列添加一个动态更新值。当行被更新时,将调用该函数, 如果没有提供任何值,则返回的值将用作列值。 如果没有提供默认值(或 $defaultFn)值,函数也将在行被插入时被调用, 并且返回的值将用作列值。

ℹ️

注意:这个值不会影响 drizzle-kit 的行为,它只在 drizzle-orm 中的运行时使用

import { integer, timestamp, text, pgTable } from "drizzle-orm/pg-core";

const table = pgTable('table', {
  updateCounter: integer('update_counter').default(sql`1`).$onUpdateFn((): SQL => sql`${table.update_counter} + 1`),
  updatedAt: timestamp('updated_at', { mode: 'date', precision: 3 }).$onUpdate(() => new Date()),
      alwaysNull: text('always_null').$type<string | null>().$onUpdate(() => null),
});

不为 null

NOT NULL 约束规定关联的列不得包含一个 NULL 值。

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,
);

主键

主键约束表示一个列,或列的组,可以用作表中行的唯一标识符。 这要求值既唯一又不为 null。

import { serial, pgTable } from "drizzle-orm/pg-core";

const table = pgTable('table', {
  id: serial('id').primaryKey(),
});
CREATE TABLE IF NOT EXISTS "table" (
  "id" serial PRIMARY KEY NOT NULL,
);
Become a Gold Sponsor