Data types
MySQL to SQL Server data types
Every MySQL data type that SQL Server stores differently, what the converter writes for it, when, and the report line.
Each row is a type from MySQL that SQL Server stores differently: what the SQL Server script gets, why, and the line the report writes about it. The rows come from the converter's own rules, so this page matches what it does.
Convert in the browser: MySQL to SQL Server opens the converter set up for this pair. The MySQL to SQL Server migration guide covers dumping, loading and the rules for keys, indexes and names.
A report line is a fix when the converter changed something and lists it, or a problem when a value or object is worth a look.
Numbers
| In MySQL | In SQL Server | Why | Report line |
|---|---|---|---|
| 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) | SQL Server has no unsigned integers except tinyint, which is 0 to 255. A wider type holds the whole unsigned range, and the check keeps negative values out as MySQL did. | unsigned_widened (fix) |
| ZEROFILL and display widths | dropped | Zero padding is a way of showing a number, not part of it. The numbers are kept; format them when you read them if the padding matters. | zerofill_dropped (fix) |
| FLOAT(M,D) | real or float, without the scale | SQL Server floats have no fixed scale. The stored values are copied as they are. | float_scale_dropped (fix) |
| DECIMAL(p,s) | decimal(p,s) up to 38 digits; nvarchar beyond | SQL Server's decimal holds 38 digits. Wider decimals are kept as text so every digit stays exact. | decimal_as_text (fix) |
Booleans and bits
| In MySQL | In SQL Server | Why | Report line |
|---|---|---|---|
| TINYINT(1), BOOL | bit when every value is 0 or 1, else smallint | MySQL's BOOL is a TINYINT(1) that can hold any number from -128 to 127. A column that only holds 0 and 1 becomes bit; one that holds 2 or -1 stays a number so no value changes meaning. | bool_kept_numeric (fix) |
| BIT(1), BIT(n) | bit; bigint up to 63 bits; decimal(20,0) for BIT(64) | A single bit is a yes or no; wider bit fields are stored as the number their bits make. | None |
Text
| In MySQL | In SQL Server | Why | Report line |
|---|---|---|---|
| CHAR(n), VARCHAR(n) | nvarchar(n) | nvarchar holds every character on every supported version, and MySQL returns CHAR values without trailing spaces, as nvarchar keeps them. | None |
| text with characters past U+FFFF (emoji) in VARCHAR(n) | nvarchar(2n), or nvarchar(max) past 4000 | nvarchar counts UTF-16 units and an emoji takes two, so the column gets room for every value. | text_length_widened (fix) |
| NUL bytes in text | kept | nvarchar can hold a NUL character, so the value is copied as it is. | None |
| text that isn't valid in its character set | the bad bytes as the replacement character | Text has to be read as characters to be written as nvarchar. | invalid_utf8_replaced (problem) |
Enums and sets
| In MySQL | In SQL Server | Why | Report line |
|---|---|---|---|
| ENUM | nvarchar with a CHECK of its values | Text with a check keeps the same values. | None |
| ENUM holding '' (MySQL's error value) | the empty value allowed by the check | MySQL stores an empty string when an invalid value goes into an ENUM in a lenient SQL mode. Those rows are kept and the check allows them. | enum_invalid_value (fix) |
| ENUM holding values outside its list | no CHECK | Values the list doesn't name would fail the check, so the check isn't created. | enum_check_skipped (problem) |
| SET | nvarchar as MySQL writes it ('a,b') | SQL Server has no arrays; the text is the one MySQL returns. | None |
Dates and times
| In MySQL | In SQL Server | Why | Report line |
|---|---|---|---|
| zero, partial or impossible dates (0000-00-00, 2024-02-30) | NULL | SQL Server only stores real calendar dates. MySQL keeps zero and impossible dates when its SQL mode allows them; they become NULL and the report counts them. | invalid_date_null (problem) |
| DEFAULT '0000-00-00' | no default | A default SQL Server can't store is left out rather than replaced with a made-up date. | zero_date_default (fix) |
| TIME | time when every value is within a day, else nvarchar | MySQL's TIME is a duration from -838:59:59 to 838:59:59; SQL Server's time is a time of day. A column with longer or negative values keeps them as text. | time_as_interval (problem) |
| YEAR | smallint with a CHECK of its range | SQL Server has no year type; the check keeps the same values MySQL allows. | None |
| DATETIME | datetime2 | A DATETIME is a wall-clock reading without a time zone, like datetime2. | None |
| TIMESTAMP | datetimeoffset in the time zone the dump states, UTC when it states none | A TIMESTAMP is a moment. Dumps state the zone they wrote it in (mysqldump writes UTC); without that, the values are read as UTC and the report says so. | timestamp_zone_assumed (problem) |
Binary
| In MySQL | In SQL Server | Why | Report line |
|---|---|---|---|
| BINARY, VARBINARY, BLOB | binary, varbinary, varbinary(max) | Bytes stay bytes. | None |
JSON, spatial and other types
| In MySQL | In SQL Server | Why | Report line |
|---|---|---|---|
| JSON | nvarchar(max) | SQL Server's JSON functions read JSON from text. An ISJSON check would refuse scalar values such as 1 or "x" before SQL Server 2022, which MySQL keeps. | None |
| GEOMETRY, POINT, POLYGON... | geometry, with each value's SRID | SQL Server's own geometry type keeps every shape and its spatial reference system. | None |
| INET4, INET6, UUID (MariaDB) | nvarchar(39), uniqueidentifier | uniqueidentifier is SQL Server's UUID; addresses are kept as text. | None |
| geometries in a dump without CREATE TABLE | geometry | MySQL's geometry format is recognised from the values. | None |
| types IntoSQL doesn't know | nvarchar(max) | Text holds any value; change the type after loading. | unknown_type (problem) |
| values that don't fit their column | NULL | A damaged or hand-written dump can hold values its column can't; they become NULL so the rest loads. | invalid_value_null (problem) |
| unreadable geometries | NULL | Bytes that aren't a geometry can't be stored as one. | bad_geometry (problem) |
| VECTOR(n) (MariaDB 11.7+) | nvarchar(max) with the floats as a JSON array | Only SQL Server 2025 has a vector type; a JSON array keeps every float on every version. | type_replaced (fix) |
Counters and identities
| In MySQL | In SQL Server | Why | Report line |
|---|---|---|---|
| AUTO_INCREMENT | IDENTITY, with the counter set past the copied ids | The copied ids load with IDENTITY_INSERT, and the counter continues after the highest one or the dump's AUTO_INCREMENT, whichever is higher. | None |
| MyISAM AUTO_INCREMENT on the second column of a key | one counter for the table | MyISAM counts per group of the key's first column; SQL Server has one counter per table. | myisam_group_autoincrement (problem) |
Other pairs
- MySQL into PostgreSQL, MySQL, MariaDB, SQLite, Oracle
- Into SQL Server from MariaDB, PostgreSQL, SQL Server, SQLite, Oracle
- Every pair