Convert Mermaid ER to Oracle
Generate production-ready Oracle SQL code from your Mermaid ER diagrams in seconds.
How the Mermaid ER to Oracle conversion works
The Oracle target renders Mermaid diagrams into 19c+ DDL with Oracle's own vocabulary: NUMBER instead of INT, VARCHAR2 instead of VARCHAR, identity clauses instead of SERIAL, and CHECK constraints standing in for enums. Double-quoted identifiers keep entity names exactly as the diagram wrote them.
Mermaid erDiagram is a Markdown-friendly notation rendered natively by GitHub, GitLab, Notion, and Obsidian — which makes it the most common way to keep an ER diagram next to the code it describes.
Entities are blocks of `type name marker` lines (markers: PK, FK, UK, INDEX), and relationships use cardinality arrows like `USER ||--o{ POST : writes` — one-to-many from USER to POST. The converter reads both, plus comment directives for everything the base syntax can't express.
Paste your Mermaid ER source into the editor above and the engine parses it into an
intermediate schema — tables, columns, relationships, indexes — then generates
Oracle 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 Mermaid ER reference documents the
full vocabulary.
Worked example: an e-commerce schema
A complete Mermaid ER diagram and the exact Oracle 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:
erDiagram
CUSTOMER ||--o{ ORDER : places
PRODUCT ||--o{ ORDER : "ordered in"
CUSTOMER {
int id PK
string email UK
%% ::NN
string name
%% ::DEFAULT(now())
timestamp created_at
}
PRODUCT {
int id PK
string sku UK
%% ::CHECK(price > 0)
decimal price
%% ::ENUM(draft, active, retired)
string status
}
ORDER {
int id PK
int customer_id FK
int product_id FK
%% ::DEFAULT(0)
decimal total
} CREATE TABLE "customer" (
"id" NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
"email" VARCHAR2(255) UNIQUE,
"name" VARCHAR2(255) NOT NULL,
"created_at" TIMESTAMP DEFAULT now()
);
CREATE TABLE "order" (
"id" NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
"customer_id" NUMBER,
"product_id" NUMBER,
"total" NUMBER DEFAULT 0
);
CREATE TABLE "product" (
"id" NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
"sku" VARCHAR2(255) UNIQUE,
"price" NUMBER CHECK (price > 0),
"status" VARCHAR2(255) CHECK ("status" IN ('draft', 'active', 'retired'))
);
ALTER TABLE "order"
ADD CONSTRAINT "fk_order_customer_id"
FOREIGN KEY ("customer_id") REFERENCES "customer"("id");
ALTER TABLE "order"
ADD CONSTRAINT "fk_order_product_id"
FOREIGN KEY ("product_id") REFERENCES "product"("id"); Primary keys came out as NUMBER GENERATED ALWAYS AS IDENTITY — the modern Oracle auto-increment, no sequence-plus-trigger boilerplate. The ::ENUM directive became a CHECK ("status" IN (…)) on a VARCHAR2 column since Oracle has no enum type, and ::CHECK(price > 0) passed straight through. Foreign keys use the same named ALTER TABLE form as PostgreSQL and MySQL.
What the generator emits for Oracle
- CREATE TABLE statements with double-quoted identifiers for Oracle 19c+
- VARCHAR2, NUMBER, and CLOB types sized for Oracle conventions
- CHECK ("col" IN (…)) constraints for ::ENUM(...) columns
- ALTER TABLE … ADD CONSTRAINT foreign keys with deterministic names
- COMMENT ON TABLE / COMMENT ON COLUMN statements
Type mapping: Mermaid ER to Oracle
Diagram column types are logical — the generator maps each one to the idiomatic Oracle type. These are the exact mappings the engine uses:
| Diagram type | Oracle type | Notes |
|---|---|---|
int | NUMBER | |
string | VARCHAR2(255) | use varchar(n) in the diagram to control length |
text | CLOB | |
decimal | NUMBER | decimal(10,2) passes precision through |
boolean | NUMBER(1) | Oracle has no boolean column type |
date | DATE | Oracle DATE includes time-of-day |
timestamp | TIMESTAMP | |
uuid | RAW(16) | compact binary storage |
bigint | NUMBER(19) | |
float | BINARY_DOUBLE |
Keys, relationships, and enums
Primary keys emit as NUMBER columns with PRIMARY KEY constraints. Auto-increment uses Oracle conventions rather than a SERIAL keyword, and composite keys emit a table-level constraint.
Relationships emit `ALTER TABLE … ADD CONSTRAINT fk_<table>_<column>` statements after all tables exist, with ON DELETE actions from the ::RELATIONSHIP directive.
Oracle has no enum type, so `::ENUM(active, inactive)` emits `VARCHAR2(255) CHECK ("status" IN ('active', 'inactive'))` — enforced at the database level via the CHECK constraint.
Frequently asked questions
Which Oracle versions can run the generated DDL?
It targets 19c and newer — GENERATED ALWAYS AS IDENTITY requires 12c+, and the quoting/constraint style is tested against current releases. For older versions you'd swap identity columns for sequences and triggers by hand.
How are enums enforced without a native enum type?
As CHECK (col IN (…)) constraints on VARCHAR2 columns — the database still rejects invalid values, there's just no separate type object like PostgreSQL's CREATE TYPE.
How does the converter handle booleans for Oracle?
As NUMBER(1) — Oracle has no boolean column type in SQL. 0/1 is the standard convention and maps cleanly to booleans in every Oracle driver.
What do enum columns become in Oracle DDL?
VARCHAR2(255) with a CHECK (col IN (…)) constraint. You keep database-level validation even though Oracle has no native enum type.