Skip to content

SQL to Prisma Schema

Convert a MySQL or MariaDB dump into a Prisma 6 or 7 schema.prisma with models, both relation sides and native types, warning about what will not convert.

Read in your browser and never uploaded. Only CREATE TABLE, ALTER TABLE and CREATE INDEX are read; INSERT data is skipped. Importing replaces the schema you are designing.

Add a table on the left, load an example, or open a project file to start designing.

Generated files

Generated files appear here as you design.

Diagnostics appear here after you paste your input.

Processed locally in your browser. Your data never leaves your device.

About this SQL to Prisma schema converter

Paste MySQL or MariaDB table definitions and get a Prisma schema: one model per table, both sides of every foreign key written as relation fields, native database types where Prisma needs them, and a plain list of anything that does not convert. It reads the SQL itself (nothing is executed and nothing leaves your browser). This page is the Prisma entry point of the Database Schema Studio, so the imported schema is fully editable, and the same schema can also produce Laravel migrations.

How to use it

  1. Paste CREATE TABLE statements or a structure-only dump, or open a .sql file, then Import.
  2. Choose the Prisma version and the database the schema targets.
  3. Read the diagnostics: they list what was skipped, approximated or renamed.
  4. Copy schema.prisma (and prisma.config.ts for Prisma 7) or download them as a ZIP.

A worked example

This SQL:

CREATE TABLE `users` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `users_email_unique` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `posts` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `user_id` bigint unsigned NOT NULL,
  `title` varchar(200) NOT NULL,
  `published` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `posts_user_id_foreign` (`user_id`),
  CONSTRAINT `posts_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

becomes these two models (Prisma 7, MySQL):

model User {
  id        BigInt    @id @default(autoincrement()) @db.UnsignedBigInt
  name      String    @db.VarChar(255)
  email     String    @unique(map: "users_email_unique") @db.VarChar(255)
  createdAt DateTime? @map("created_at") @db.Timestamp(0)
  updatedAt DateTime? @map("updated_at") @db.Timestamp(0)
  posts     Post[]

  @@map("users")
}

model Post {
  id        BigInt  @id @default(autoincrement()) @db.UnsignedBigInt
  userId    BigInt  @map("user_id") @db.UnsignedBigInt
  title     String  @db.VarChar(200)
  published Boolean @default(false)
  user      User    @relation(fields: [userId], references: [id], onDelete: Cascade, map: "posts_user_id_foreign")

  @@map("posts")
}

Note what changed: table names become singular PascalCase models with @@map; created_at becomes createdAt with @map; the foreign key becomes a user field on Post and a posts list on User (Prisma needs both); tinyint(1) is a Boolean; the constraint names from the SQL are kept through map; and the index that only supported the foreign key is not listed, because MySQL creates it from the key.

Type mapping (MySQL to Prisma)

How MySQL column types are written in a Prisma schema
MySQL typePrisma field type
tinyint(1)Boolean
tinyintInt @db.TinyInt
intInt
int unsignedInt @db.UnsignedInt
bigintBigInt
bigint unsignedBigInt @db.UnsignedBigInt
decimal(8,2)Decimal @db.Decimal(8, 2)
floatFloat @db.Float
doubleFloat @db.Double
char(36)String @db.Char(36)
varchar(100)String @db.VarChar(100)
varchar(191)String
textString @db.Text
longtextString @db.LongText
dateDateTime @db.Date
datetimeDateTime @db.DateTime(0)
timestampDateTime @db.Timestamp(0)
jsonJson
blobBytes @db.Blob
yearUnsupported("year")

A native attribute is written only when it differs from Prisma's default for the database (so varchar(191), MySQL's default String, stays a plain String). Other databases use their own natives: for PostgreSQL, uuid is @db.Uuid, jsonb is @db.JsonB and unsigned integers are ignored with a warning.

What Prisma cannot express

  • Generated columns and CHECK constraints (dropped, with a warning).
  • SetNull on required columns, and SetDefault on MySQL (the action is dropped).
  • Indexes on JSON or Unsupported columns, and whole-column indexes on MySQL TEXT and BLOB (a 191-character prefix is written).
  • Relations to non-unique columns or between columns of different types.

Frequently asked questions

How is this different from prisma db pull?
prisma db pull connects to a live database and introspects it. This page needs no database and no connection: you paste the SQL (a mysqldump --no-data export, SHOW CREATE TABLE output or phpMyAdmin structure export) and get a schema.prisma from it. It is useful when you only have a dump, want to review before touching a database, or want to see what does not convert. For a running database, db pull remains the authoritative source.
Which Prisma versions does it write?
Prisma 7 (the default) and Prisma 6. They differ only in the header: Prisma 7 uses the prisma-client generator and keeps the connection URL in prisma.config.ts (included as a second file), while Prisma 6 uses prisma-client-js and a url line in the datasource block. Models, fields and relations are identical. The output is validated against the real Prisma 6 and 7 parsers in our tests. Prisma 8 has not been verified.
Why are model and field names changed?
Prisma models are PascalCase and singular by convention, and fields are camelCase. Tables and columns keep their real names through @@map and @map, so the database is unchanged. Choose "Keep column names" to leave field names as the columns are named. Names Prisma reserves are adjusted and every adjustment is listed.
Why did a relation not appear?
Prisma only accepts a relation that points at a unique key with matching types. If the referenced columns are not the primary key or a unique constraint, or the two columns have different types, the foreign key columns stay as plain fields and a warning says why. A table with no primary key or unique constraint on required columns is written with @@ignore, as prisma db pull does.
What happens to enums, comments and unusual types?
MySQL and PostgreSQL enums become named enum blocks (values that are not valid identifiers keep the stored value through @map). SQLite has no enum type, so the column is a String. Comments become /// documentation comments. Types Prisma has no scalar for (year, set, bit, spatial) are written with Unsupported(), which keeps the column but hides it from Prisma Client.
Is my SQL uploaded?
No. Reading and generating happen in your browser. The SQL is never sent anywhere or stored, and nothing is executed.