Convert Mermaid ER to Oracle

Generate production-ready Oracle SQL code from your Mermaid ER diagrams in seconds.

oracle
Dialect: oracleTables: 2
Done.
mermaid
Live preview mermaid

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 typeOracle typeNotes
intNUMBER
stringVARCHAR2(255)use varchar(n) in the diagram to control length
textCLOB
decimalNUMBERdecimal(10,2) passes precision through
booleanNUMBER(1)Oracle has no boolean column type
dateDATEOracle DATE includes time-of-day
timestampTIMESTAMP
uuidRAW(16)compact binary storage
bigintNUMBER(19)
floatBINARY_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.

Related conversions