Skip to main content
ChartDB provides comprehensive export capabilities, allowing you to generate SQL DDL scripts, DBML definitions, and visual exports for documentation and deployment.

Export Formats

ChartDB supports multiple export formats for different use cases:

SQL DDL

Generate CREATE TABLE statements for any database

DBML

Export to Database Markup Language

PNG/SVG

Export diagram as image

JSON

Export raw diagram data

SQL Export

Native Dialect Export

Export SQL optimized for your diagram’s database type:
export const exportBaseSQL = ({
    diagram,
    targetDatabaseType,
    isDBMLFlow = false,
    onlyRelationships = false,
}: {
    diagram: Diagram;
    targetDatabaseType: DatabaseType;
    isDBMLFlow?: boolean;
    onlyRelationships?: boolean;
}): string => {
    // Export SQL for the target database
    switch (diagram.databaseType) {
        case DatabaseType.POSTGRESQL:
            return exportPostgreSQL({ diagram, onlyRelationships });
        case DatabaseType.MYSQL:
            return exportMySQL({ diagram, onlyRelationships });
        case DatabaseType.SQL_SERVER:
            return exportMSSQL({ diagram, onlyRelationships });
        case DatabaseType.SQLITE:
            return exportSQLite({ diagram, onlyRelationships });
    }
};

PostgreSQL Export

Full PostgreSQL DDL with advanced features:
CREATE TABLE public.users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    tags TEXT[],
    settings JSONB,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE public.posts (
    id SERIAL PRIMARY KEY,
    user_id INT NOT NULL,
    title VARCHAR(255) NOT NULL,
    content TEXT,
    published BOOLEAN DEFAULT false,
    CONSTRAINT fk_posts_user_id 
        FOREIGN KEY (user_id) 
        REFERENCES public.users(id)
        ON DELETE CASCADE
);

MySQL Export

MySQL-specific DDL with engine and charset:
CREATE TABLE `users` (
  `id` INT AUTO_INCREMENT PRIMARY KEY,
  `email` VARCHAR(255) NOT NULL,
  `name` VARCHAR(100),
  `status` ENUM('active', 'inactive') DEFAULT 'active',
  `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY `uk_users_email` (`email`),
  INDEX `idx_users_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE `posts` (
  `id` INT AUTO_INCREMENT PRIMARY KEY,
  `user_id` INT NOT NULL,
  `title` VARCHAR(255) NOT NULL,
  `content` TEXT,
  INDEX `idx_posts_user_id` (`user_id`),
  CONSTRAINT `fk_posts_user_id` 
    FOREIGN KEY (`user_id`) 
    REFERENCES `users` (`id`)
    ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

SQL Server Export

T-SQL with SQL Server-specific syntax:
CREATE TABLE [dbo].[Users] (
    [Id] INT IDENTITY(1,1) PRIMARY KEY,
    [Email] NVARCHAR(255) NOT NULL,
    [Name] NVARCHAR(100),
    [CreatedAt] DATETIME2 DEFAULT GETDATE(),
    CONSTRAINT [UQ_Users_Email] UNIQUE ([Email])
);

CREATE NONCLUSTERED INDEX [IX_Users_Email]
ON [dbo].[Users] ([Email]);

CREATE TABLE [dbo].[Posts] (
    [Id] INT IDENTITY(1,1) PRIMARY KEY,
    [UserId] INT NOT NULL,
    [Title] NVARCHAR(255) NOT NULL,
    [Content] NVARCHAR(MAX),
    CONSTRAINT [FK_Posts_UserId] 
        FOREIGN KEY ([UserId]) 
        REFERENCES [dbo].[Users] ([Id])
        ON DELETE CASCADE
);

SQLite Export

SQLite-compatible DDL:
CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    email TEXT NOT NULL UNIQUE,
    name TEXT,
    created_at TEXT DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_users_email ON users(email);

CREATE TABLE posts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL,
    title TEXT NOT NULL,
    content TEXT,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

CREATE INDEX idx_posts_user_id ON posts(user_id);

Cross-Dialect Export

ChartDB supports deterministic cross-dialect conversions:

PostgreSQL to MySQL

export const exportPostgreSQLToMySQL = ({
    diagram,
    onlyRelationships = false,
}: {
    diagram: Diagram;
    onlyRelationships?: boolean;
}): string => {
    // Convert PostgreSQL types to MySQL equivalents
    // Handle unsupported features
    // Generate MySQL-compatible DDL
};

Type Mappings

PostgreSQLMySQLNotes
SERIALINT AUTO_INCREMENTAuto-increment
BIGSERIALBIGINT AUTO_INCREMENTLarge auto-increment
TEXTTEXTDirect mapping
BYTEABLOBBinary data
BOOLEANTINYINT(1)True/False
TIMESTAMPDATETIMEDate and time
JSONBJSONJSON data (MySQL 5.7+)
TEXT[]JSONArrays converted to JSON
UUIDCHAR(36)UUID as string
Array types are converted to JSON in MySQL. Check constraints may need manual adjustment.

PostgreSQL to SQL Server

export const exportPostgreSQLToMSSQL = ({
    diagram,
    onlyRelationships = false,
}: {
    diagram: Diagram;
    onlyRelationships?: boolean;
}): string => {
    // Convert PostgreSQL types to SQL Server equivalents
    // Handle schema differences
    // Generate T-SQL DDL
};

Type Mappings

PostgreSQLSQL ServerNotes
SERIALINT IDENTITY(1,1)Auto-increment
TEXTNVARCHAR(MAX)Unicode text
BYTEAVARBINARY(MAX)Binary data
BOOLEANBITTrue/False
TIMESTAMPDATETIME2High precision
JSONBNVARCHAR(MAX)JSON as text
UUIDUNIQUEIDENTIFIERNative UUID

Unsupported Features Detection

ChartDB detects features that don’t translate well:
interface UnsupportedFeature {
    type: 'array' | 'enum' | 'check_constraint' | 'index_type';
    tableName: string;
    fieldName?: string;
    description: string;
    suggestion: string;
}

const detectUnsupportedFeatures = (
    diagram: Diagram,
    targetDatabase: DatabaseType
): UnsupportedFeature[] => {
    const features: UnsupportedFeature[] = [];
    
    // Check for arrays (not supported in MySQL/SQL Server)
    // Check for PostgreSQL-specific index types
    // Check for enum types
    // Check for complex check constraints
    
    return features;
};
Warnings are included in export output:
-- WARNING: The following features are not fully supported:
-- 1. Array type 'tags' in table 'users' converted to JSON
-- 2. GIN index 'idx_users_tags' converted to regular index
-- 3. Check constraint uses PostgreSQL-specific regex

DBML Export

Export to DBML format with two variants:

Standard DBML

With standalone relationship definitions:
Table users {
  id int [pk, increment]
  email varchar(255) [unique, not null]
  name varchar(100)
  created_at timestamp [default: `now()`]
  
  Note: 'User accounts table'
}

Table posts {
  id int [pk, increment]
  user_id int [not null]
  title varchar(255) [not null]
  content text
}

Ref: posts.user_id > users.id

Inline DBML

With inline relationship references:
Table users {
  id int [pk, increment]
  email varchar(255) [unique, not null]
  name varchar(100)
  created_at timestamp [default: `now()`]
}

Table posts {
  id int [pk, increment]
  user_id int [not null, ref: > users.id]
  title varchar(255) [not null]
  content text
}

DBML Export Features

Schema information is preserved:
const restoreTableSchemas = (dbml: string, tables: DBTable[]): string => {
    // Add schema qualifiers to tables
    // Format: Table "schema"."table_name"
};

DBML Conversion Pipeline

The DBML export uses a round-trip process:
1

Generate SQL

Export diagram to SQL for the diagram’s database type
2

Sanitize SQL

Clean SQL for DBML parser compatibility:
export const sanitizeSQLforDBML = (sql: string): string => {
    // Remove PostgreSQL-specific syntax
    // Fix constraint name duplicates
    // Handle self-referencing foreign keys
    // Normalize type casting
};
3

Parse to DBML

Use @dbml/core importer to convert SQL to DBML
4

Restore Features

Add back features lost in conversion:
  • Table schemas
  • Index types
  • Check constraints
  • Auto-increment attributes
  • Comments and notes
5

Convert References

Optionally convert to inline reference format

Export Options

Only Relationships

Export just the foreign key constraints:
const sql = exportBaseSQL({
    diagram,
    targetDatabaseType: DatabaseType.POSTGRESQL,
    onlyRelationships: true, // Only FK constraints
});
Output:
-- Foreign key constraints
ALTER TABLE posts 
ADD CONSTRAINT fk_posts_user_id 
    FOREIGN KEY (user_id) 
    REFERENCES users(id);

ALTER TABLE comments 
ADD CONSTRAINT fk_comments_post_id 
    FOREIGN KEY (post_id) 
    REFERENCES posts(id);

Custom Type Handling

Control how custom types are exported:
const supportsCustomTypes = (databaseType: DatabaseType): boolean => {
    return databaseType === DatabaseType.POSTGRESQL;
};

// For databases without custom type support,
// enums are converted to CHECK constraints
if (!supportsCustomTypes(targetDatabase)) {
    // Convert enum to VARCHAR with CHECK
    // status VARCHAR(20) CHECK (status IN ('pending', 'active'))
}

Comment Support

Include table and column comments where supported:
const databaseTypesWithCommentSupport = [
    DatabaseType.POSTGRESQL,
    DatabaseType.MYSQL,
    DatabaseType.ORACLE,
];

if (databaseTypesWithCommentSupport.includes(targetDatabase)) {
    // Add COMMENT ON statements or inline comments
}

Visual Export

Export diagram as image:

PNG Export

Raster image for documentation

SVG Export

Vector image for scalability

Export Quality

Control export resolution and quality:
interface ExportImageOptions {
    format: 'png' | 'svg';
    quality?: number; // 0-100 for PNG
    backgroundColor?: string;
    padding?: number;
    includeAreas?: boolean;
    includeNotes?: boolean;
}

JSON Export

Export raw diagram data for backup or migration:
{
  "id": "diagram_123",
  "name": "E-commerce Database",
  "databaseType": "postgresql",
  "tables": [...],
  "relationships": [...],
  "customTypes": [...],
  "createdAt": "2024-03-04T10:30:00Z",
  "updatedAt": "2024-03-04T12:45:00Z"
}
This format preserves:
  • All table definitions
  • Field attributes and constraints
  • Relationships and cardinalities
  • Custom types and enums
  • Table positions and colors
  • Notes and areas
  • Metadata and timestamps

Export Caching

SQL exports are cached for performance:
const generateCacheKey = (
    diagram: Diagram,
    targetDatabaseType: DatabaseType,
    options: ExportOptions
): string => {
    return `${diagram.id}_${targetDatabaseType}_${JSON.stringify(options)}`;
};

const getFromCache = (key: string): string | null => {
    const cached = cache.get(key);
    if (cached && cached.timestamp > diagram.updatedAt) {
        return cached.sql;
    }
    return null;
};
Cache is invalidated when diagram changes.

Best Practices

For production deployments:
  1. Review generated SQL before running on production databases
  2. Test migrations on a staging environment first
  3. Include comments for better documentation
  4. Export both SQL and DBML for version control
  5. Use cross-dialect warnings to identify compatibility issues
  6. Validate foreign keys are in correct order

Advanced Export Features

Default Value Formatting

Default values are intelligently formatted:
const formatDefaultValue = (value: string): string => {
    // SQL keywords (no quotes)
    if (['TRUE', 'FALSE', 'NULL', 'CURRENT_TIMESTAMP'].includes(value)) {
        return value;
    }
    
    // Function calls (no quotes)
    if (value.includes('(') && value.includes(')')) {
        return value;
    }
    
    // Numbers (no quotes)
    if (/^-?\d+(\.\d+)?$/.test(value)) {
        return value;
    }
    
    // Strings (quoted and escaped)
    return `'${value.replace(/'/g, "''")}'`;
};

Identifier Quoting

Table and field names are quoted when needed:
const getQuotedTableName = (table: DBTable): string => {
    const needsQuoting = /[^a-zA-Z0-9_]/.test(table.name);
    
    if (table.schema) {
        return needsQuoting 
            ? `"${table.schema}"."${table.name}"`
            : `${table.schema}.${table.name}`;
    }
    
    return needsQuoting ? `"${table.name}"` : table.name;
};

Troubleshooting

Ensure referenced tables are created before referencing tables in the export order.
Review cross-dialect warnings for incompatible types and adjust manually.
Some database-specific features may not translate. Use native export when possible.
For MySQL, ensure charset and collation settings match your application needs.

Next Steps

AI Migration

Use AI for advanced database migrations

Diagram Editor

Edit your diagram before export

Build docs developers (and LLMs) love