Skip to main content

Drizzle ORM Schema Generator

TalkingSchema's AI copilot generates complete Drizzle ORM TypeScript schemas from any ERD — including pgTable / mysqlTable / sqliteTable declarations, column type mappings, relations() definitions, and inferred $inferSelect / $inferInsert type exports. The output is ready to drop into a src/db/schema.ts file.

Outputs are provided as TypeScript code blocks, with an option to download as a .ts file coming soon


How to Generate a Drizzle Schema

Step 1 — Open or build your schema in TalkingSchema

Import from a live database, upload a DDL file, or describe your system. The AI copilot has full awareness of your schema at all times.

Step 2 — Ask the AI copilot

Generate a Drizzle ORM TypeScript schema for this ERD.
Use pgTable for PostgreSQL. Include relations(), foreign keys,
and $inferSelect / $inferInsert type exports.
Export this schema as Drizzle ORM definitions. Group related
tables into separate files: schema/suppliers.ts, schema/orders.ts,
schema/logistics.ts.

Step 3 — Integrate the output

Paste the generated TypeScript into your src/db/schema.ts (or whichever path your Drizzle config points to). Update your drizzle.config.ts if needed.


Example Output

Using the Global Sustainable Supply Chain (GSSC) schema:

// schema/suppliers.ts
import {
pgTable,
uuid,
varchar,
boolean,
timestamp,
pgEnum,
} from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";

export const carbonTierEnum = pgEnum("carbon_tier", ["A", "B", "C", "D"]);

export const suppliers = pgTable("suppliers", {
supplierId: uuid("supplier_id").primaryKey().defaultRandom(),
companyName: varchar("company_name", { length: 200 }).notNull(),
country: varchar("country", { length: 100 }).notNull(),
carbonTier: carbonTierEnum("carbon_tier").notNull(),
certification: varchar("certification", { length: 100 }),
isActive: boolean("is_active").default(true),
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow(),
});

export type Supplier = typeof suppliers.$inferSelect;
export type NewSupplier = typeof suppliers.$inferInsert;

// schema/products.ts
import {
pgTable,
uuid,
varchar,
boolean,
timestamp,
numeric,
} from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";
import { suppliers } from "./suppliers";

export const products = pgTable("products", {
productId: uuid("product_id").primaryKey().defaultRandom(),
sku: varchar("sku", { length: 50 }).unique().notNull(),
name: varchar("name", { length: 200 }).notNull(),
category: varchar("category", { length: 100 }).notNull(),
unitWeightKg: numeric("unit_weight_kg", { precision: 8, scale: 3 }),
unitCostUsd: numeric("unit_cost_usd", { precision: 12, scale: 4 }).notNull(),
carbonIntensityScore: numeric("carbon_intensity_score", {
precision: 5,
scale: 2,
}),
supplierId: uuid("supplier_id")
.notNull()
.references(() => suppliers.supplierId),
isActive: boolean("is_active").default(true),
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow(),
});

export type Product = typeof products.$inferSelect;
export type NewProduct = typeof products.$inferInsert;

// schema/orders.ts
import {
pgTable,
uuid,
varchar,
date,
timestamp,
numeric,
integer,
check,
pgEnum,
} from "drizzle-orm/pg-core";
import { sql } from "drizzle-orm";
import { suppliers } from "./suppliers";
import { products } from "./products";
import { warehouses } from "./warehouses";

export const orderStatusEnum = pgEnum("order_status", [
"draft",
"confirmed",
"shipped",
"received",
"cancelled",
]);

export const purchaseOrders = pgTable("purchase_orders", {
poId: uuid("po_id").primaryKey().defaultRandom(),
supplierId: uuid("supplier_id")
.notNull()
.references(() => suppliers.supplierId),
warehouseId: uuid("warehouse_id")
.notNull()
.references(() => warehouses.warehouseId),
orderDate: date("order_date").notNull(),
expectedDelivery: date("expected_delivery"),
status: orderStatusEnum("status"),
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow(),
});

export const purchaseOrderItems = pgTable("purchase_order_items", {
itemId: uuid("item_id").primaryKey().defaultRandom(),
poId: uuid("po_id")
.notNull()
.references(() => purchaseOrders.poId, { onDelete: "cascade" }),
productId: uuid("product_id")
.notNull()
.references(() => products.productId),
quantity: integer("quantity").notNull(),
unitCostUsd: numeric("unit_cost_usd", { precision: 12, scale: 4 }).notNull(),
});

export type PurchaseOrder = typeof purchaseOrders.$inferSelect;
export type NewPurchaseOrder = typeof purchaseOrders.$inferInsert;

// schema/relations.ts — declare all relation metadata for joins
import { relations } from "drizzle-orm";
import { suppliers, products } from "./suppliers";
import { purchaseOrders, purchaseOrderItems } from "./orders";

export const suppliersRelations = relations(suppliers, ({ many }) => ({
products: many(products),
purchaseOrders: many(purchaseOrders),
}));

export const productsRelations = relations(products, ({ one, many }) => ({
supplier: one(suppliers, {
fields: [products.supplierId],
references: [suppliers.supplierId],
}),
purchaseOrderItems: many(purchaseOrderItems),
}));

export const purchaseOrdersRelations = relations(
purchaseOrders,
({ one, many }) => ({
supplier: one(suppliers, {
fields: [purchaseOrders.supplierId],
references: [suppliers.supplierId],
}),
items: many(purchaseOrderItems),
}),
);

export const purchaseOrderItemsRelations = relations(
purchaseOrderItems,
({ one }) => ({
purchaseOrder: one(purchaseOrders, {
fields: [purchaseOrderItems.poId],
references: [purchaseOrders.poId],
}),
product: one(products, {
fields: [purchaseOrderItems.productId],
references: [products.productId],
}),
}),
);

Customizing the Output

RequirementPrompt addition
MySQL instead of PostgreSQL"Use mysqlTable instead of pgTable. Adjust type imports."
SQLite"Use sqliteTable from drizzle-orm/sqlite-core."
Single file output"Put all tables in a single schema.ts file."
Include drizzle.config.ts"Also generate a drizzle.config.ts for PostgreSQL with DATABASE_URL."
Add index declarations"Add index() for all foreign key columns and status enums."
Kebab-case file names"Output as separate files using kebab-case: purchase-orders.ts"

Frequently Asked Questions

Does the output include relations() for joins?

Yes. By default, TalkingSchema generates both the table declarations and the relations() metadata required for Drizzle's query API (.with() clauses). Ask explicitly if you only need table definitions without relations.

Does it handle enums?

Yes. PostgreSQL enum types defined in the ERD are mapped to pgEnum() declarations, placed before the tables that reference them.

Can I request Drizzle schema migrations output?

Yes. Ask: "Generate a Drizzle migration SQL from the current schema changes." The AI produces the ALTER TABLE and CREATE TABLE statements compatible with drizzle-kit push or drizzle-kit generate.