Convert PlantUML to MySQL
Generate production-ready MySQL SQL code from your PlantUML diagrams in seconds.
How the PlantUML to MySQL conversion works
The MySQL target reads PlantUML's native semantics — * mandatory markers, <<UNIQUE>> and <<FK>> stereotypes — and renders them with MySQL conventions: backtick quoting, VARCHAR(255) strings, inline ENUM column types, and deterministic constraint names that keep future migrations sane.
PlantUML entity diagrams are the standard in many enterprise and Java-adjacent teams, with first-class tooling in IDEs and Confluence. Entities declare mandatory fields with a leading *, and stereotypes like <<FK>> mark key columns.
Entities are `entity Name { … }` blocks — a leading `*` marks mandatory (NOT NULL) fields, `<<FK>>` marks foreign keys, and relationships use the same cardinality arrows as Mermaid (`User ||--o{ Post`). Quoted display names (`entity "User Account" as ua`) become table comments.
Paste your PlantUML source into the editor above and the engine parses it into an
intermediate schema — tables, columns, relationships, indexes — then generates
MySQL DDL from that model. Anything the diagram
syntax can't express (NOT NULL, defaults, enums, CHECK constraints, composite indexes)
you add with comment directives like ' ::NN, ::DEFAULT(now()) on the line
above a column. The PlantUML reference documents the
full vocabulary.
Worked example: a library loan schema
A complete PlantUML diagram and the exact MySQL output the generator produces for it — different from the starter diagram in the editor above, so you can see a second real conversion end to end:
@startuml
entity Member {
* id : int <<PK>>
* email : string <<UNIQUE>>
name : string
joined_at : timestamp
}
entity Book {
* id : int <<PK>>
* isbn : string <<UNIQUE>>
title : string
' ::ENUM(available, loaned, lost)
status : string
}
entity Loan {
* id : int <<PK>>
member_id : int <<FK>>
book_id : int <<FK>>
' ::DEFAULT(now())
loaned_at : timestamp
}
Member ||--o{ Loan : borrows
Book ||--o{ Loan : "loaned as"
@enduml CREATE TABLE `member` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`email` VARCHAR(255) NOT NULL UNIQUE,
`name` VARCHAR(255),
`joined_at` DATETIME
);
CREATE TABLE `book` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`isbn` VARCHAR(255) NOT NULL UNIQUE,
`title` VARCHAR(255),
`status` ENUM('available', 'loaned', 'lost')
);
CREATE TABLE `loan` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`member_id` INT,
`book_id` INT,
`loaned_at` DATETIME DEFAULT now()
);
ALTER TABLE `loan`
ADD CONSTRAINT `fk_loan_member_id`
FOREIGN KEY (`member_id`) REFERENCES `member`(`id`);
ALTER TABLE `loan`
ADD CONSTRAINT `fk_loan_book_id`
FOREIGN KEY (`book_id`) REFERENCES `book`(`id`); The * markers on email and isbn became NOT NULL without any directive, and the ' ::ENUM comment turned into an inline ENUM('available', 'loaned', 'lost') — MySQL's native form, where the PostgreSQL twin of this page creates a separate type. Relationship labels with spaces ("loaned as") are fine: they only name the arrow in the diagram and never leak into SQL.
What the generator emits for MySQL
- CREATE TABLE statements with backtick-quoted identifiers, ready for InnoDB
- AUTO_INCREMENT primary keys for single integer PK columns
- inline ENUM(…) column types for ::ENUM(...) columns
- ALTER TABLE … ADD CONSTRAINT foreign keys with ON DELETE / ON UPDATE actions
- inline COMMENT column options and COMMENT = table options
- CREATE INDEX / CREATE UNIQUE INDEX for composite and named indexes
Type mapping: PlantUML to MySQL
Diagram column types are logical — the generator maps each one to the idiomatic MySQL type. These are the exact mappings the engine uses:
| Diagram type | MySQL type | Notes |
|---|---|---|
int | INT | INT AUTO_INCREMENT when it is the auto-increment primary key |
string | VARCHAR(255) | use varchar(n) in the diagram to control length |
text | TEXT | longtext / mediumtext map to their native equivalents |
decimal | DECIMAL | decimal(10,2) passes precision through |
boolean | TINYINT(1) | the MySQL convention for booleans |
date | DATE | |
timestamp | DATETIME | |
uuid | CHAR(36) | stored as the canonical text form |
bigint | BIGINT | |
blob | BLOB |
Keys, relationships, and enums
A single `int id PK` column becomes `` `id` INT AUTO_INCREMENT PRIMARY KEY ``. Composite primary keys emit a table-level `PRIMARY KEY (a, b)` without auto-increment.
Relationships emit `ALTER TABLE … ADD CONSTRAINT` statements with deterministic `fk_<table>_<column>` names — important on MySQL, where anonymous constraints make later migrations painful. ON DELETE / ON UPDATE actions come from the ::RELATIONSHIP directive.
MySQL supports enums natively on the column, so `::ENUM(active, inactive)` emits `status ENUM('active', 'inactive')` inline — no separate type object, no CHECK constraint.
Frequently asked questions
Do quoted relationship labels like "loaned as" affect the generated SQL?
No — the label names the relationship in the diagram; the SQL only uses the entities and cardinality. You can label arrows freely for readers without changing the schema.
How do PlantUML's mandatory fields interact with MySQL's ENUM columns?
Independently, same as SQL itself: * controls NOT NULL, ::ENUM controls the value set. status in the example is an enum but nullable because it has no * — add one and it becomes ENUM(…) NOT NULL.
Does the generated MySQL DDL use native ENUM columns?
Yes. ::ENUM(...) values are emitted as an inline ENUM(…) column type, which MySQL validates at the storage layer. PostgreSQL output uses CREATE TYPE instead; SQLite and Oracle fall back to CHECK constraints.
How are booleans represented?
As TINYINT(1), the MySQL convention. Most drivers and ORMs read TINYINT(1) back as a boolean automatically.