---
title: "Migrate MySQL to SQL Server in your browser"
description: "Migrate a MySQL or MariaDB database to SQL Server: convert its dump into a script with the same tables, keys and data, and a report of every change."
canonical: https://intosql.com/mysql-to-sql-server
last_updated: 2026-10-15
---

# Migrate MySQL to SQL Server in your browser

Drop a dump from mysqldump, mariadb-dump, mysqlpump, phpMyAdmin or Adminer, as .sql or .sql.gz, and download a script for SQL Server with the same tables, keys, indexes and data. Every value SQL Server can't hold as it is, and every object it doesn't carry, is listed in the report.

[MySQL to SQL Server migration guide](https://intosql.com/docs/migrations/mysql-to-sql-server)

[MySQL to SQL Server data types](https://intosql.com/docs/types/mysql-to-sql-server)

## What changes from MySQL to SQL Server

Each row is a rule the converter applies, with the report line it writes when the rule changes something in your data.

| In MySQL | In SQL Server | Report line |
| --- | --- | --- |
| TINYINT(1), BOOL | bit when every value is 0 or 1, else smallint | `bool_kept_numeric` |
| UNSIGNED integers | TINYINT UNSIGNED as tinyint; the others the next wider integer with a CHECK that it isn't negative, BIGINT UNSIGNED as bigint when every value fits, else decimal(38,0) | `unsigned_widened` |
| ZEROFILL and display widths | dropped | `zerofill_dropped` |
| FLOAT(M,D) | real or float, without the scale | `float_scale_dropped` |
| DECIMAL(p,s) | decimal(p,s) up to 38 digits; nvarchar beyond | `decimal_as_text` |
| BIT(1), BIT(n) | bit; bigint up to 63 bits; decimal(20,0) for BIT(64) |  |
| zero, partial or impossible dates (0000-00-00, 2024-02-30) | NULL | `invalid_date_null` |
| NOT NULL columns with values that become NULL | NOT NULL dropped | `not_null_relaxed` |
| DEFAULT '0000-00-00' | no default | `zero_date_default` |
| TIME | time when every value is within a day, else nvarchar | `time_as_interval` |
| YEAR | smallint with a CHECK of its range |  |
| CHAR(n), VARCHAR(n) | nvarchar(n) |  |
| text with characters past U+FFFF (emoji) in VARCHAR(n) | nvarchar(2n), or nvarchar(max) past 4000 | `text_length_widened` |
| DATETIME | datetime2 |  |
| TIMESTAMP | datetimeoffset in the time zone the dump states, UTC when it states none | `timestamp_zone_assumed` |
| ENUM | nvarchar with a CHECK of its values |  |
| ENUM holding '' (MySQL's error value) | the empty value allowed by the check | `enum_invalid_value` |
| ENUM holding values outside its list | no CHECK | `enum_check_skipped` |
| SET | nvarchar as MySQL writes it ('a,b') |  |
| JSON | nvarchar(max) |  |
| NUL bytes in text | kept |  |
| text that isn't valid in its character set | the bad bytes as the replacement character | `invalid_utf8_replaced` |
| text decoded twice (Ã±) | copied as it is | `mojibake_suspected` |
| AUTO_INCREMENT | IDENTITY, with the counter set past the copied ids |  |
| MyISAM AUTO_INCREMENT on the second column of a key | one counter for the table | `myisam_group_autoincrement` |
| ON UPDATE CURRENT_TIMESTAMP | an AFTER UPDATE trigger | `on_update_trigger` |
| ON UPDATE CURRENT_TIMESTAMP on a table without a primary key | not carried | `on_update_without_key` |
| generated columns | computed columns, PERSISTED when the source stores them |  |
| generated columns with functions SQL Server lacks | a plain column | `generated_not_translated` |
| INVISIBLE columns | regular columns | `invisible_column` |
| CHECK constraints | translated, inline in CREATE TABLE |  |
| CHECK constraints with functions SQL Server lacks | not created | `check_skipped` |
| CHECK ... NOT ENFORCED | not created | `check_not_enforced` |
| defaults with functions SQL Server lacks | no default | `default_not_translated` |
| keys and indexes on a prefix, c(20) | an index on the whole column | `prefix_whole_column` |
| FULLTEXT indexes | not created | `fulltext_not_created` |
| SPATIAL indexes | not created | `spatial_index_not_created` |
| functional indexes, and indexes on columns of unlimited length | not created | `index_skipped` |
| foreign keys | after the data WITH NOCHECK, then checked with a warning on orphans |  |
| ON DELETE or ON UPDATE that cascades in a cycle or along a second path | NO ACTION | `foreign_key_action_dropped` |
| foreign keys to columns without a unique key | not created | `foreign_key_skipped` |
| table and column names | as written; renamed when they differ only in case | `identifier_renamed` |
| names over 116 characters | shortened | `name_shortened` |
| GEOMETRY, POINT, POLYGON... | geometry, with each value's SRID |  |
| INET4, INET6, UUID (MariaDB) | nvarchar(39), uniqueidentifier |  |
| BINARY, VARBINARY, BLOB | binary, varbinary, varbinary(max) |  |
| PARTITION BY | one table | `partitions_dropped` |
| WITH SYSTEM VERSIONING (MariaDB) | a table with the current rows | `system_versioning_dropped` |
| MyISAM, MEMORY and other engines | a regular table | `engine_dropped` |
| views, triggers, procedures, functions and events | listed in the report | `not_converted_objects` |
| dumps without CREATE TABLE | types read from the values | `no_schema` |
| geometries in a dump without CREATE TABLE | geometry |  |
| _ci collations | the database's collation, usually case-insensitive |  |
| SET NAMES utf8 from utf8mb4 tables | converted, with a warning | `dump_lost_four_byte_chars` |
| dumps without SET NAMES whose text isn't UTF-8 | read as Latin-1 (Windows-1252) | `charset_guessed` |
| sjis, cp932, gbk, big5 dumps | read as UTF-8, with a warning | `unsupported_charset` |
| UNHEX('..'), CONVERT(b'..', UNSIGNED), CONVERT(".." USING x), ST_GeomFromText('..') in rows | evaluated |  |
| other expressions in rows | NULL | `expression_value` |
| DEFAULT in VALUES | the column's default value | `default_keyword_filled` |
| DEFAULT in VALUES without a literal default | NULL | `default_keyword_null` |
| REPLACE and INSERT IGNORE | plain rows | `replace_as_insert` |
| types IntoSQL doesn't know | nvarchar(max) | `unknown_type` |
| values that don't fit their column | NULL | `invalid_value_null` |
| unreadable geometries | NULL | `bad_geometry` |
| CREATE SEQUENCE (MariaDB) | CREATE SEQUENCE ... AS bigint, at its next value |  |
| VECTOR(n) (MariaDB 11.7+) | nvarchar(max) with the floats as a JSON array | `type_replaced` |

## Load the script into SQL Server

The script creates the tables, copies the rows, then adds keys, indexes and foreign keys, so it loads fast and stops at the first error.

```shell
sqlcmd -b -f 65001 -S localhost -d mydb -i mysql.sql_server.sql
```

Foreign keys are added WITH NOCHECK and then checked. If a row points to a row that doesn't exist, the script says which constraint and leaves it unchecked, instead of failing half way.

For a large dump, run sqlcmd on the same machine as the server. Each batch of up to 1000 rows commits on its own, so the transaction log stays small.

## Dump MySQL for the best result

The converter reads what the dump holds. These options keep more of your data in it:

- --default-character-set=utf8mb4 keeps emoji and other 4-byte characters, which a utf8 dump loses before the converter sees it.
- --hex-blob writes binary columns as hexadecimal, which survives copying between systems.
- --routines --triggers --events add those objects to the dump, so the report can list them.

## What isn't converted

Views, triggers, stored procedures, functions and events are written in each database's own language. They are listed in the report by name, never dropped silently, so you can rewrite them for SQL Server.

## Questions about MySQL to SQL Server

### Is my dump uploaded?

No. The converter runs in your browser and reads the dump from your disk in pieces, so it never leaves your computer. The desktop app and the command line convert on your computer too.

### How large can the dump be?

The converter never holds the whole dump in memory: it reads the file twice, by ranges, and writes the script as it goes. Multi-gigabyte dumps convert in the browser, in the desktop app and with the command line.

### Does it read MariaDB dumps?

Yes. Dumps from mariadb-dump and from MariaDB 10.3 to 12 convert the same way, including MariaDB's INET6, INET4 and UUID columns.

### What happens to 0000-00-00 dates?

SQL Server has no zero date, so they become NULL and the column accepts NULL. The report says how many there were in each column.

### Are AUTO_INCREMENT values kept?

Yes. Each AUTO_INCREMENT column becomes an IDENTITY column, every row keeps its id, and the next id continues after the highest one, or after the table's AUTO_INCREMENT if that is higher.

### Does TINYINT(1) become boolean?

It becomes bit only when every value in the column is 0 or 1. If it holds other numbers, such as 2 or -1, it stays a number and the report says why, so no value turns into 1 by accident.

### What about stored procedures and triggers?

They are listed in the report by name and not converted, because each database writes them in its own language. ON UPDATE CURRENT_TIMESTAMP is the exception: it becomes a SQL Server trigger.

### Which SQL Server versions does the script load on?

SQL Server 2017 to 2025. The same script loads on each of them, stopping at the first error if anything goes wrong.

## From MySQL

- [MySQL to PostgreSQL](https://intosql.com/mysql-to-postgresql)
- [MySQL to MySQL](https://intosql.com/mysql-to-mysql)
- [MySQL to MariaDB](https://intosql.com/mysql-to-mariadb)
- [MySQL to SQLite](https://intosql.com/mysql-to-sqlite)
- [MySQL to Oracle](https://intosql.com/mysql-to-oracle)

## Into SQL Server

- [MariaDB to SQL Server](https://intosql.com/mariadb-to-sql-server)
- [PostgreSQL to SQL Server](https://intosql.com/postgresql-to-sql-server)
- [SQL Server to SQL Server](https://intosql.com/sql-server-to-sql-server)
- [SQLite to SQL Server](https://intosql.com/sqlite-to-sql-server)
- [Oracle to SQL Server](https://intosql.com/oracle-to-sql-server)

## Guide and every pair

- [SQL Server to MySQL](https://intosql.com/sql-server-to-mysql)
- [MySQL to SQL Server migration guide](https://intosql.com/docs/migrations/mysql-to-sql-server)
- [MySQL to SQL Server data types](https://intosql.com/docs/types/mysql-to-sql-server)
- [Every database pair](https://intosql.com/database-migration)
