DSL syntax

.dbschema is a database structure format you can read at a glance: one column per line, relations declared on their own. Paste it into the workspace or open it in VS Code and the diagram appears.

Quick start

Two tables and one foreign key make the smallest possible diagram. Copy this, then paste it into Import in the workspace.

dbschema
table Users {
  PK Id    bigint        not null
     Email nvarchar(255) not null "Login email"
}

table Orders {
  PK Id     bigint not null
  FK UserId bigint not null
}

relation FK_Orders_Users {
  Orders.UserId N -> 1 Users.Id
}

Only three things to know: table declares a table, each line is a column, and relation declares a relation. Anything after // is a comment.

Tables

table Name "description" { … }. You can prefix the name with a schema (sales.Orders); without one it is dbo. The description is optional and shows next to the card title. Names are case-sensitive; keywords are not.

dbschema
table Users "System users" {
  PK Id bigint not null "User ID"
}

// With a schema; dbo when omitted
table sales.Orders {
  PK Id bigint not null
}

Columns

The format is [flags] Name Type [null | not null] [default value] ["comment"], one per line. Aligning columns is just for readability; the amount of whitespace does not matter.

dbschema
table Products {
  PK  Id        bigint         not null "Product ID"
  UQ  Sku       nvarchar(64)   not null
      Name      nvarchar(200)  not null
      Price     decimal(18,2)  not null default 0
      Note      nvarchar(4000) null     "Notes"
      IsActive  bit            not null default 1
}

Flags

FlagMeaning
PKPrimary key; implies not null
FKForeign key marker; visual only, declare the link with relation
UQUnique
IDXIndexed marker; real indexes use the index statement

Rules

CaseHow it is read
Several flags at oncePK UQ Id bigint
No null / not nullNullable by default (except PK)
One type argumentLength, e.g. nvarchar(255)
Two type argumentsPrecision and scale, e.g. decimal(18,2)
String at the end of the lineColumn comment, shown on the card
defaultA number, string or identifier, e.g. default 0, default "draft"

Groups

Groups are your own functional categories (say, "Orders" or "Members"). They are not database schemas and can span several. Tables in the same group are laid out together in one color, and the toolbar can show a single group.

dbschema
// 1. Declare the group and list its members
group Identity "Identity and access" {
  Users
  Roles
}

// 2. Declare only the description; mark members on each table
group Sales "Orders and payments"

table Orders in Sales {
  PK Id bigint not null
}

A table belongs to at most one group. If you write table X in G and G is not declared, G becomes a group with no description.

Indexes

Indexes are declared on their own; composite indexes keep the column order you list. When a foreign key column has no index, the workspace shows a hint (the diagram is not affected).

dbschema
index IX_Posts_Author_CreatedAt on Posts(AuthorId, CreatedAt)
unique index UX_Users_Email on Users(Email)

Relations

The left side of the arrow holds the foreign key; the right side is the table it points to. Posts.AuthorId N -> 1 Users.Id reads "many Posts belong to one User". This direction also decides upstream / downstream when you focus a table.

dbschema
relation FK_Posts_Users {
  Posts.AuthorId N -> 1 Users.Id
}

// Composite foreign key
relation FK_OrderLines_Orders {
  OrderLines.(OrderId, TenantId) N -> 1 Orders.(Id, TenantId)
}
SyntaxMeaning
N -> 1Many-to-one (most common: the left side holds the foreign key)
1 -> NOne-to-many
1 -> 1One-to-one
N -> MMany-to-many

The FK flag on a column does not create a relation by itself; every line on the diagram comes from a relation.

Other formats

SQL

In the workspace, Import → SQL takes plain CREATE TABLE for MySQL, SQL Server, PostgreSQL and SQLite. Column-level REFERENCES and table-level FOREIGN KEY both become relations, and the result is saved as DSL. In VS Code, use "DBSchema: Import SQL as .dbschema".

sql
CREATE TABLE users (
  id    bigint PRIMARY KEY,
  email text NOT NULL
);

CREATE TABLE orders (
  id      bigint PRIMARY KEY,
  user_id bigint NOT NULL REFERENCES users(id)
);

Markdown

Name the file .schema.md and put the DSL in a fenced code block tagged dbschema, so docs and structure live in one file.

markdown
# Orders module

```dbschema
table Orders {
  PK Id bigint not null
}
```

JSON

Name the file .schema.json. It is the full structure the workspace exports, handy for scripts or backups.

Shortcuts

Shared by the web app and the VS Code extension; rows marked "web" only work on the web.

KeysWhat it does
Ctrl / Cmd + FSearch tables or columns
Ctrl / Cmd + wheelZoom the canvas
Drag backgroundPan (move mode) / box-select (select mode)
Click a table nameFocus: related tables light up, the rest dim; click again to clear
Click a columnColumn focus: only that column and its foreign key partners light up
Double-click a table or columnJump to its DSL definition
TabMove through tables with the keyboard
Enter / SpaceFocus the current table (press again to clear)
Shift + EnterJump to the table definition
EscClear focus, close dialogs
Ctrl / Cmd + click a tableMulti-select (web); Delete removes the selection
DeleteDelete the clicked or selected tables; undo from the notice (web)
Ctrl / Cmd + ASelect every table on screen (web)
Ctrl / Cmd + ZUndo the last edit (web)
Ctrl / Cmd + Shift + Z, Ctrl + YRedo (web)
Ctrl / Cmd + DDuplicate the selected or focused tables (web)
Ctrl / Cmd + CCopy the DSL of the selected or focused tables (web)
+ / -Zoom in / out
Shift + 1Zoom to fit the whole diagram

Errors and hints

SCHEMA_* codes are errors that make the diagram wrong; LINT_* codes are only design hints. A parse error never sinks the whole file: everything that can be read is still drawn, and the line that could not be read is listed with its line and column.

CodeMeaning and fix
SCHEMA_PARSE_ERRORThis line cannot be read. The message gives line:column; usually a missing bracket, a stray symbol or a misspelled keyword.
SCHEMA_DUPLICATE_TABLE / COLUMN / INDEXA table, column or index with the same name is declared twice.
SCHEMA_UNKNOWN_TABLE / COLUMNA relation, index or group points to a table or column that does not exist. Check the case (Users ≠ users).
SCHEMA_RELATION_SOURCE_NOT_FOUND / TARGET_NOT_FOUNDOne side of the relation arrow cannot be found.
SCHEMA_INVALID_CARDINALITYCardinality can only be 1, N or M.
SCHEMA_INVALID_COMPOSITE_RELATIONEvery line in one relation block must point to the same source / target tables.
SCHEMA_DUPLICATE_GROUP / CONFLICTING_GROUPA group is declared twice, or a table is put in two groups.
LINT_FK_NO_INDEXHint: the foreign key column has no index, so JOINs may be slow. The diagram is not affected.
LINT_NO_PKHint: this table has no primary key.
LINT_EMPTY_TABLEHint: this table has no columns.
LINT_NAMING / LINT_TYPE_SUFFIXHint: naming style is inconsistent.