ChartDB provides comprehensive export capabilities, allowing you to generate SQL DDL scripts, DBML definitions, and visual exports for documentation and deployment.
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:
Tables
Indexes
Custom Types
Check Constraints
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
PostgreSQL MySQL Notes 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
PostgreSQL SQL Server Notes 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
Table Restoration
Enum Export
Index Restoration
Check Constraints
Schema information is preserved: const restoreTableSchemas = ( dbml : string , tables : DBTable []) : string => {
// Add schema qualifiers to tables
// Format: Table "schema"."table_name"
};
Custom types are exported as enums: Enum order_status {
pending
processing
shipped
delivered
}
Table orders {
id int [pk]
status order_status [default: 'pending']
}
Index types are preserved: Table posts {
id int [pk]
tags text[]
Indexes {
tags [type: gin, name: 'idx_posts_tags']
}
}
Check constraints are included: Table products {
id int [pk]
price decimal(10,2)
quantity int
checks {
`price > 0` [name: 'check_positive_price']
`quantity >= 0`
}
}
DBML Conversion Pipeline
The DBML export uses a round-trip process:
Generate SQL
Export diagram to SQL for the diagram’s database type
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
};
Parse to DBML
Use @dbml/core importer to convert SQL to DBML
Restore Features
Add back features lost in conversion:
Table schemas
Index types
Check constraints
Auto-increment attributes
Comments and notes
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'))
}
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:
Review generated SQL before running on production databases
Test migrations on a staging environment first
Include comments for better documentation
Export both SQL and DBML for version control
Use cross-dialect warnings to identify compatibility issues
Validate foreign keys are in correct order
Advanced Export Features
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