Sql To Drizzle

SQL DDL to Drizzle ORM Schema Generator (PostgreSQL, MySQL, SQLite)

Convert SQL CREATE TABLE statements into strongly-typed Drizzle ORM schemas with pgTable, mysqlTable, and sqliteTable definitions.

Presets:
Database Dialect:
Schema Syntax:
Column Keys:
SQL DDL StatementsPostgreSQL
import {
  boolean,
  index,
  integer,
  jsonb,
  numeric,
  pgEnum,
  pgTable,
  serial,
  text,
  timestamp,
  uniqueIndex,
  uuid,
  varchar
} from 'drizzle-orm/pg-core';
import { relations } from 'drizzle-orm';
import { createSelectSchema, createInsertSchema } from 'drizzle-zod';

// Enums
export const userRoleEnum = pgEnum('user_role', ['CUSTOMER', 'ADMIN', 'VENDOR']);

export const orderStatusEnum = pgEnum('order_status', ['PENDING', 'PAID', 'PROCESSING', 'SHIPPED', 'DELIVERED', 'CANCELLED']);


// Tables
export const users = pgTable('users', {
  id: uuid('id').defaultRandom().primaryKey(),
  email: varchar('email', { length: 255 }).notNull().unique(),
  fullName: varchar('full_name', { length: 120 }),
  role: userRoleEnum('role').notNull().default('CUSTOMER'),
  isActive: boolean('is_active').notNull().default(true),
  metadata: jsonb('metadata'),
  createdAt: timestamp('created_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),
  updatedAt: timestamp('updated_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),
});

export const userProfiles = pgTable('user_profiles', {
  id: uuid('id').defaultRandom().primaryKey(),
  userId: uuid('user_id').notNull().unique().references(() => users.id, { onDelete: 'cascade' }),
  avatarUrl: varchar('avatar_url', { length: 500 }),
  phone: varchar('phone', { length: 30 }),
  shippingAddress: text('shipping_address'),
  taxIdentifier: varchar('tax_identifier', { length: 50 }),
});

export const products = pgTable('products', {
  id: serial('id').primaryKey(),
  sku: varchar('sku', { length: 64 }).notNull().unique(),
  title: varchar('title', { length: 200 }).notNull(),
  description: text('description'),
  price: numeric('price', { precision: 10, scale: 2 }).notNull().default(0.00),
  inventory: integer('inventory').notNull().default(0),
  isPublished: boolean('is_published').notNull().default(true),
  createdAt: timestamp('created_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),
}, (table) => [
  index('idx_products_sku').on(table.sku)
]);

export const orders = pgTable('orders', {
  id: uuid('id').defaultRandom().primaryKey(),
  customerId: uuid('customer_id').notNull().references(() => users.id, { onDelete: 'restrict' }),
  orderNumber: varchar('order_number', { length: 64 }).notNull().unique(),
  status: orderStatusEnum('status').notNull().default('PENDING'),
  totalAmount: numeric('total_amount', { precision: 12, scale: 2 }).notNull().default(0.00),
  notes: text('notes'),
  createdAt: timestamp('created_at', { withTimezone: true, mode: 'date' }).notNull().defaultNow(),
}, (table) => [
  index('idx_orders_customer').on(table.customerId)
]);

export const orderItems = pgTable('order_items', {
  id: serial('id').primaryKey(),
  orderId: uuid('order_id').notNull().references(() => orders.id, { onDelete: 'cascade' }),
  productId: integer('product_id').notNull().references(() => products.id, { onDelete: 'restrict' }),
  quantity: integer('quantity').notNull().default(1),
  unitPrice: numeric('unit_price', { precision: 10, scale: 2 }).notNull(),
}, (table) => [
  uniqueIndex('uq_order_product').on(table.orderId, table.productId)
]);


// Relations
export const usersRelations = relations(users, ({ many }) => ({
  userProfileses: many(userProfiles),
  orderses: many(orders),
}));

export const userProfilesRelations = relations(userProfiles, ({ one }) => ({
  user: one(users, {
    fields: [userProfiles.userId],
    references: [users.id],
  }),
}));

export const productsRelations = relations(products, ({ many }) => ({
  orderItemses: many(orderItems),
}));

export const ordersRelations = relations(orders, ({ one, many }) => ({
  customer: one(users, {
    fields: [orders.customerId],
    references: [users.id],
  }),
  orderItemses: many(orderItems),
}));

export const orderItemsRelations = relations(orderItems, ({ one }) => ({
  order: one(orders, {
    fields: [orderItems.orderId],
    references: [orders.id],
  }),
  product: one(products, {
    fields: [orderItems.productId],
    references: [products.id],
  }),
}));


// TypeScript Inferred Types
export type User = typeof users.$inferSelect;
export type NewUser = typeof users.$inferInsert;
export type UserProfile = typeof userProfiles.$inferSelect;
export type NewUserProfile = typeof userProfiles.$inferInsert;
export type Product = typeof products.$inferSelect;
export type NewProduct = typeof products.$inferInsert;
export type Order = typeof orders.$inferSelect;
export type NewOrder = typeof orders.$inferInsert;
export type OrderItem = typeof orderItems.$inferSelect;
export type NewOrderItem = typeof orderItems.$inferInsert;

// Drizzle-Zod Schemas
export const selectUserSchema = createSelectSchema(users);
export const insertUserSchema = createInsertSchema(users);
export const selectUserProfileSchema = createSelectSchema(userProfiles);
export const insertUserProfileSchema = createInsertSchema(userProfiles);
export const selectProductSchema = createSelectSchema(products);
export const insertProductSchema = createInsertSchema(products);
export const selectOrderSchema = createSelectSchema(orders);
export const insertOrderSchema = createInsertSchema(orders);
export const selectOrderItemSchema = createSelectSchema(orderItems);
export const insertOrderItemSchema = createInsertSchema(orderItems);
Tables Parsed5Distinct schema models
Columns Converted34Typed table attributes
Foreign KeysPostgreSQL
4Relational references & links

Zero-Upload Local Privacy

All SQL parsing and TypeScript schema synthesis execute 100% in your local browser sandbox. Your database architecture never leaves your machine.

Multi-Dialect Drizzle Precision

Full support for pgTable (PostgreSQL), mysqlTable (MySQL), and sqliteTable (SQLite) with accurate type mappings, enums, indexes, and constraints.

Type-Safe Relations & Inferences

Generates Drizzle ORM typed relations(), $inferSelect, $inferInsert types, and optional drizzle-zod validation schemas ready for production.

Technical Reference & Architecture Guide

SQL DDL to Drizzle ORM Schema Generator (PostgreSQL, MySQL, SQLite) — Reference Guide

Convert SQL CREATE TABLE statements into strongly-typed Drizzle ORM schemas with pgTable, mysqlTable, and sqliteTable definitions.

Key Parameters & Controls

Target DialectEnum ('postgresql' | 'mysql' | 'sqlite')

Target Drizzle database dialect and corresponding core library imports (drizzle-orm/pg-core, drizzle-orm/mysql-core, or drizzle-orm/sqlite-core).

Default: postgresql
Column Identifier CasingEnum ('camelCase' | 'snake_case')

Controls whether TypeScript schema field keys retain database snake_case or are transformed into idiomatic camelCase identifiers.

Default: camelCase
Generate Inferred Types ($inferSelect / $inferInsert)Boolean

Appends strongly typed schema inference declarations (typeof table.$inferSelect and typeof table.$inferInsert) for each generated table.

Default: true
Export SyntaxEnum ('named' | 'schema-object')

Specifies whether to output individual named schema constants (export const users = ...) or bundle all definitions into a unified schema container object.

Default: named

Pro Tips & Best Practices

SQL REFERENCES constraints

SQL REFERENCES constraints are automatically compiled into .references(() => otherTable.id) arrow function callbacks, avoiding circular import runtime issues.

PostgreSQL Custom Enums with pgEnum

PostgreSQL CREATE TYPE ... AS ENUM statements are extracted into reusable pgEnum() declarations with full TypeScript union inference.

Multi-column primary keys

Multi-column primary keys, unique constraints, and composite indexes are mapped into the third table callback function (table) => [...] cleanly.

Common Gotchas & Troubleshooting

Unsupported vendor-specific DDL syntax or stored procedure definitions

Remove database-specific storage engine directives (e.g., ENGINE=InnoDB) or trigger definitions, and ensure inputs are valid standard CREATE TABLE statements.

Circular foreign key references causing TypeScript evaluation loops

Use Drizzle's arrow function callback syntax for .references(() => targetTable.id) or separate tables across modular schema files with Drizzle relations().

Frequently Asked Questions

How does the converter handle primary keys and auto-incrementing serials?▼

In PostgreSQL, SERIAL and BIGSERIAL map to serial() and bigserial(). In MySQL, AUTO_INCREMENT is transformed into .autoincrement(), and SQLite INTEGER PRIMARY KEY maps to integer().primaryKey({ autoIncrement: true }).

Are the generated schemas compatible with drizzle-kit push and generate?▼

Yes, all generated output adheres to standard Drizzle ORM TypeScript conventions and is 100% compatible with drizzle-kit migrations, introspection, and Studio.

How are nullability and default expressions handled?▼

Columns without a NOT NULL modifier are nullable by default. NOT NULL attributes append .notNull(), while SQL DEFAULT values are translated into .default(...) or $defaultFn().

Is my SQL schema data uploaded to any server or third-party service?▼

No. The SQL tokenizer, parser, and TypeScript Drizzle schema generator run entirely in your local browser runtime with zero server-side transmission.

Related Tools & Utilities

All Tools →