Skip to main content

DBML (Database Markup Language)

DBML (Database Markup Language) is an open-source, human-readable text format for defining relational database schemas. It was created by the Holistics team as part of the dbdiagram.io project and first released in 2018.

DBML's goal is to provide a concise, readable schema definition format that is easier to write and review than raw SQL DDL — closer to how engineers naturally think about tables and relationships.


Why DBML Exists

SQL DDL (Data Definition Language) is the standard for creating database objects, but it has significant readability drawbacks:

  • Verbose syntax for relationships (FOREIGN KEY (column_name) REFERENCES table_name(column_name))
  • Relationship direction is implicit, not explicit
  • No standardized way to add descriptions or metadata inline
  • Different syntax across database engines (PostgreSQL, MySQL, SQL Server, etc.)

DBML addresses these issues with a cleaner, engine-agnostic syntax that expresses the same information more readably.


DBML Syntax Overview

A DBML file consists of three main block types: Table, Ref, and Project.

Table block

Table users {
id integer [primary key, increment]
email varchar(255) [unique, not null]
full_name varchar(255)
created_at timestamp [default: `now()`]
is_active boolean [default: true]

Note: "Core user account table"
}

Key syntax elements:

  • Column definition: column_name data_type [constraint, constraint]
  • [primary key] — marks the primary key column
  • [increment] — auto-increment / SERIAL
  • [unique] — unique constraint
  • [not null] — NOT NULL constraint
  • [default: value] — default value; use backticks for SQL expressions
  • Note: "..." — inline description for the table or column

Ref block (relationships)

// One-to-many: one user has many orders
Ref: orders.user_id > users.id

// One-to-one: each user has one profile
Ref: user_profiles.user_id - users.id

// Many-to-many (via junction table)
Ref: order_products.order_id > orders.id
Ref: order_products.product_id > products.id

Relationship operators:

  • > — many-to-one (the table on the left has many rows for one row on the right)
  • < — one-to-many (the table on the left has one row for many rows on the right)
  • - — one-to-one

The explicit > and < operators make relationship direction readable at a glance — unlike SQL FOREIGN KEY syntax, where the cardinality must be inferred.

Project block

Project ecommerce_db {
database_type: 'PostgreSQL'
Note: 'E-commerce platform database schema'
}

The Project block adds metadata to the schema file. It is optional but useful for documentation purposes.

Index block

Table orders {
id integer [primary key, increment]
user_id integer [not null]
status varchar(50)
created_at timestamp

indexes {
user_id
(user_id, status) [name: 'idx_orders_user_status']
created_at [name: 'idx_orders_created']
}
}

Enum definition

Enum order_status {
pending
processing
shipped
delivered
cancelled
}

Table orders {
id integer [primary key, increment]
status order_status [not null, default: 'pending']
}

Complete DBML Example

Project ecommerce {
database_type: 'PostgreSQL'
}

Table users {
id integer [primary key, increment]
email varchar(255) [unique, not null]
full_name varchar(255) [not null]
created_at timestamp [default: `now()`]
}

Table products {
id integer [primary key, increment]
name varchar(255) [not null]
sku varchar(100) [unique, not null]
price decimal(10,2)
category_id integer
}

Table orders {
id integer [primary key, increment]
user_id integer [not null]
total decimal(10,2) [not null]
created_at timestamp [default: `now()`]
}

Table order_items {
id integer [primary key, increment]
order_id integer [not null]
product_id integer [not null]
quantity integer [not null]
unit_price decimal(10,2) [not null]
}

Ref: orders.user_id > users.id
Ref: order_items.order_id > orders.id
Ref: order_items.product_id > products.id

DBML vs SQL DDL

AspectDBMLSQL DDL
ReadabilityHigh — concise, familiar syntaxModerate — verbose with lots of boilerplate
Relationship definitionRef: orders.user_id > users.id (one line)Multi-line FOREIGN KEY ... REFERENCES block
Relationship directionExplicit (>, <, -)Implicit — reader must infer from REFERENCES
Database engineEngine-agnosticEngine-specific (PostgreSQL, MySQL, SQL Server syntax differ)
Executable❌ Cannot be executed directly — must be compiled to DDL✅ Executed directly by the database engine
Inline documentationNote: field on tables and columnsLimited — only SQL comments (--)
Toolingdbdiagram.io, TalkingSchema, dbml-to-sql, prisma-dbml-generatorAny database client, migration tool, ORM

DBML is not a replacement for SQL DDL — it is a schema-as-code authoring format that compiles to SQL DDL. The workflow is: author in DBML → compile to SQL DDL for a specific target engine → execute the DDL against the database.


How TalkingSchema Uses DBML

TalkingSchema has full round-trip DBML support — both import and export.

DBML import

You can import a DBML schema into TalkingSchema from multiple sources:

  • Import → Paste DBML — paste DBML text directly into the import dialog
  • Import → Upload DBML file — upload a .dbml file from your filesystem

Once imported, TalkingSchema parses the DBML and renders all tables, columns, data types, and relationships on the interactive ERD canvas. You can then use the AI copilot to iterate on the imported schema.

DBML export

TalkingSchema can export any schema as DBML from Export → DBML. The exported DBML file contains:

  • All table definitions with column names, data types, and constraints
  • Primary key and unique index annotations
  • Foreign key relationships as Ref: blocks
  • Column-level notes where descriptions have been added

The exported DBML is compatible with dbdiagram.io, dbml-to-sql, and other DBML-consuming tools.

DBML as internal representation

TalkingSchema uses DBML as its internal schema representation format. When the AI copilot generates or modifies a schema, it operates on the DBML representation, which is then rendered visually on the ERD canvas and made available for export to all supported formats.


Tools That Support DBML

ToolDBML support
dbdiagram.ioNative — DBML is the primary input format
TalkingSchemaFull import and export
dbml-to-sqlCLI tool: DBML → SQL DDL for multiple dialects
prisma-dbml-generatorPrisma schema → DBML
dbdocs.ioDBML → hosted schema documentation

Frequently Asked Questions

Who created DBML?

DBML was created by Holistics, the company behind dbdiagram.io. It was first published as an open-source format in 2018. The DBML specification is maintained on GitHub.

Is DBML a standard?

DBML is not an ISO or ANSI standard. It is an open-source format created and maintained by Holistics. It has gained adoption through the popularity of dbdiagram.io and the dbml-to-sql library. It is not versioned with formal releases in the same way as SQL standards.

Can DBML represent all SQL DDL features?

DBML covers the most common relational schema features: tables, columns, data types, primary keys, foreign keys, unique constraints, indexes, and enums. It does not cover all database-specific features: stored procedures, triggers, views, check constraints (in full generality), and platform-specific object types (Snowflake streams/tasks, PostgreSQL JSONB operators, etc.). For schemas that rely heavily on these features, SQL DDL is the more complete representation.

Is TalkingSchema's DBML output compatible with dbdiagram.io?

Yes. TalkingSchema's DBML export follows the DBML specification and is compatible with dbdiagram.io's import. You can take a TalkingSchema-exported DBML file, paste it into dbdiagram.io, and the diagram will render correctly. The reverse is also true — DBML exported from dbdiagram.io can be imported into TalkingSchema.

How do I convert DBML to SQL DDL?

TalkingSchema exports SQL DDL directly from the Export → SQL menu, supporting PostgreSQL, MySQL, SQLite, and MSSQL dialects. Alternatively, the open-source @dbml/cli tool converts DBML to SQL for any supported dialect from the command line:

npx @dbml/cli/bin/dbml2sql --postgres schema.dbml