Guide
From SQL tables to a Drizzle schema or TypeORM entities
Drizzle ORM keeps its schema in TypeScript: each table is a call such as pgTable('users', {...}) with a typed builder for every column. That gives excellent type safety, but rewriting an existing database in that form by hand is tedious and error-prone. This converter reads CREATE TABLE statements and writes the Drizzle schema, or TypeORM entity classes if that is the ORM your project uses.
Three Drizzle dialects
Drizzle has a separate core package per database, and column builders differ between them. For PostgreSQL the output imports from drizzle-orm/pg-core and uses builders such as serial, varchar, numeric, timestamp with withTimezone, jsonb and uuid. For MySQL it uses mysql-core with int, varchar, decimal, datetime and mysqlEnum, adding .autoincrement() where the SQL had AUTO_INCREMENT. For SQLite it maps everything onto SQLite’s few storage classes: integers, real, text and blob, with booleans and timestamps stored as integers in boolean or timestamp mode.
Keys, defaults and constraints
Each column becomes a builder followed by a chain of modifiers. Single-column primary keys get .primaryKey(), NOT NULL becomes .notNull(), UNIQUE becomes .unique(), literal defaults become .default(...) and now() or CURRENT_TIMESTAMP becomes .defaultNow(). A composite primary key, as on a join table, is written in the table’s extra configuration with primaryKey({ columns: [...] }).
Foreign keys and enums
References become .references(() => users.id, { onDelete: 'cascade' }). The arrow function lets tables refer to each other regardless of the order they are declared in. PostgreSQL enums are declared once at the top with pgEnum('order_status', [...]) and then used like a column builder, which is how Drizzle creates the matching CREATE TYPE in migrations.
A worked example
From the Sample, the orders table becomes pgTable('orders', {...}) with id: bigserial('id', { mode: 'number' }).primaryKey(), userId: integer('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }), status: orderStatusEnum('status').notNull().default("pending"), total: numeric('total', { precision: 10, scale: 2 }).notNull() and placedAt: timestamp('placed_at', { withTimezone: true }).notNull().defaultNow(). The enum itself appears above the tables as export const orderStatusEnum = pgEnum('order_status', ['pending', 'paid', 'shipped', 'cancelled']).
The TypeORM option
TypeORM describes tables as decorated classes instead. Each table becomes an @Entity({ name: 'orders' }) class, auto-increment keys become @PrimaryGeneratedColumn, other columns @Column with their SQL type, length, precision and nullability, and foreign keys a @ManyToOne property with @JoinColumn naming the column. This suits NestJS projects and codebases that already use TypeORM 0.3.
What to finish by hand
Drizzle’s relations() helpers, which power the relational query API, are not generated; they are short to write once the tables exist. Defaults that call database functions other than now(), CHECK constraints, views and triggers are skipped. Review numeric columns that hold money, since numeric values arrive in JavaScript as strings.
Picking Drizzle or TypeORM
Both ORMs can describe the same database, but they feel different in code. Drizzle keeps the schema as plain objects and writes queries that look like SQL, with types inferred straight from the table definitions, so there is no code generation step. TypeORM uses classes and decorators, has an Active Record or repository style, and is the default in many NestJS templates. If you are starting fresh in a TypeScript project, Drizzle’s output is shorter and easier to review; if the rest of the codebase already uses TypeORM entities, generate those so the new tables match the old ones.
Wiring it up
Save the Drizzle output as src/db/schema.ts, create the client with the driver for your database, and pass the schema to it. From then on, typeof users.$inferSelect gives the row type for free.
Related tools
- SQL to Prisma produces a schema.prisma from the same statements.
- TypeScript to Zod adds runtime validation for the inferred row types.
- ER Diagram Maker visualises the tables before you start.
- JSON to TypeScript types API responses that use these rows.
Checked against the current version of the SQL to Drizzle & TypeORM on .

