SQL to SQLAlchemy Model
Generate a SQLAlchemy declarative model from a SQL CREATE TABLE statement.
Related Tools
Generate a Prisma schema model from a SQL CREATE TABLE statement.
Generate a Drizzle ORM schema from a SQL CREATE TABLE statement.
Generate a TypeORM entity class from a SQL CREATE TABLE statement.
Convert CSV rows into SQL INSERT statements.
Generate Python dataclasses from a JSON document.
Generate a Sequelize model from a SQL CREATE TABLE statement.
Documentation
What is SQL to SQLAlchemy?
SQL to SQLAlchemy turns CREATE TABLE statements into classic SQLAlchemy declarative models — a class(Base) per table with __tablename__ and Column(...) attributes, the declarative_base() style used across most existing SQLAlchemy 1.x projects.
How it works
Each SQL type maps to a SQLAlchemy column type — INTEGER/SERIAL → Integer, VARCHAR(n) → String(n), DECIMAL(p,s) → Numeric(p, s) (preserving precision and scale rather than collapsing to a lossy Float), TIMESTAMP → DateTime, UUID → String(36). Unlike the JS/TS generators in this cluster, a foreign key becomes a real, functional ForeignKey('table.column') argument directly inside Column(...) — SQLAlchemy models foreign keys as a column-level constraint, not a separate relation object, so this translation is unambiguous and safe to generate. primary_key=True, autoincrement=True, nullable=False, and unique=True are added from the parsed constraints. Only literal defaults and CURRENT_TIMESTAMP/NOW() (→ default=datetime.utcnow, with from datetime import datetime added automatically) are translated into default= arguments.
Features
- One
class(Base)model per table, with__tablename__set to the real SQL name - Real, working
ForeignKey('table.column')generation for referenced columns Numeric(precision, scale)preserved fromDECIMAL/NUMERICinstead of a lossy float- Literal and
utcnowdefaults translated; everything else left as a comment - Copy or download the generated
.pymodule
Example
Input:
CREATE TABLE users ( id SERIAL PRIMARY KEY, external_id UUID DEFAULT uuid_generate_v4(), name VARCHAR(255) NOT NULL, is_active BOOLEAN DEFAULT true ); CREATE TABLE posts ( id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES users(id), title VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
Output:
from sqlalchemy import Column, Boolean, DateTime, ForeignKey, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from datetime import datetime
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True, autoincrement=True)
external_id = Column(String(36)) # SQL default not translated: uuid_generate_v4()
name = Column(String(255), nullable=False)
is_active = Column(Boolean, default=True)
class Post(Base):
__tablename__ = 'posts'
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
title = Column(String(255), nullable=False)
created_at = Column(DateTime, default=datetime.utcnow)Common errors
A DEFAULT expression the generator doesn't recognize, like uuid_generate_v4(), is left as a # SQL default not translated: uuid_generate_v4() comment rather than a guessed default= value — add the real behavior yourself, e.g. default=lambda: str(uuid.uuid4()) or a server-side default via server_default=text(...). Note that while ForeignKey is generated for you, the higher-level relationship() accessor (e.g. posts = relationship('Post', back_populates='user')) is not — that still requires you to decide the attribute name and back-reference on both classes. The generator also targets the classic declarative_base() API, not SQLAlchemy 2.0's typed Mapped/mapped_column style, so on a 2.0 codebase you'll need to convert the Column(...) lines by hand.
Best practices
Add relationship() calls immediately after pasting the models in, using the generated ForeignKey columns as your map of what needs one. Run alembic revision --autogenerate (or your migration tool of choice) against the models to catch any type mismatch with the real database before applying.
Frequently Asked Questions
Are foreign keys generated with ForeignKey()?▾
Yes — unlike the JS/TS ORM generators in this cluster, SQLAlchemy's ForeignKey('table.column') is a plain column argument rather than a separate relation object, so it's included directly: Column(Integer, ForeignKey('users.id')). You'll still want to add relationship() calls yourself for the ORM-level convenience accessors.
Does this use the newer SQLAlchemy 2.0 declarative style (Mapped / mapped_column)?▾
No — it generates the classic declarative_base() + Column(...) style, since it's still the most widely deployed pattern across existing SQLAlchemy 1.x codebases. If your project is on 2.0's typed style, the column definitions translate directly — swap Column(...) for mapped_column(...) and add type hints.
How is DEFAULT CURRENT_TIMESTAMP handled?▾
As default=datetime.utcnow (a Python callable SQLAlchemy invokes per-insert), with the needed from datetime import datetime added automatically. Other SQL default expressions aren't guessed at — only literal values and this common case are translated.
What Python type backs a DECIMAL(10,2) column?▾
Numeric(10, 2), preserving both the precision and scale from the original SQL type rather than collapsing to a generic Float, since Numeric maps to Python's Decimal and avoids floating-point rounding issues for currency-like data.