Each row is a type from SQL Server that MySQL stores differently: what the MySQL 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: SQL Server to MySQL opens the converter set up for this pair. The SQL Server to MySQL 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 SQL Server |
In MySQL |
Why |
Report line |
| decimal(p,s), money, smallmoney |
decimal(p,s); money as decimal(19,4) |
decimal holds 65 digits, more than SQL Server's 38, so every value is exact. |
None |
Booleans and bits#
| In SQL Server |
In MySQL |
Why |
Report line |
| bit |
tinyint(1) |
MySQL's BOOLEAN is TINYINT(1): 1 and 0, as bit holds them. |
None |
Text#
| In SQL Server |
In MySQL |
Why |
Report line |
| char(n), varchar(n), nchar(n), nvarchar(n), varchar(max), text |
char(n), varchar(n) up to 1024 characters, text types beyond |
Text keeps every character as utf8mb4. A column in a key is varchar(768) at most, the longest a key holds, and so is text with a default, which MySQL 5.7 gives only to varchar. |
None |
| NUL characters in text |
kept |
The value is copied with the NUL character escaped. |
None |
| text that isn't valid in its encoding |
the bad bytes as the replacement character |
The script is UTF-8 and every value has to be valid text. |
invalid_utf8_replaced (problem) |
Dates and times#
| In SQL Server |
In MySQL |
Why |
Report line |
| datetime, datetime2, smalldatetime |
datetime(p) |
A datetime is a wall-clock reading in both. |
None |
| datetime2(7), time(7) and datetimeoffset(7) |
six digits of a second, the seventh cut |
MySQL keeps microseconds; the seventh digit (100 nanoseconds) is cut, never rounded, so no value moves to the next second or day. |
fraction_cut (fix) |
| datetimeoffset |
datetime(p) in UTC |
MySQL's TIMESTAMP only reaches 2038, so moments are stored as datetime in UTC, the same instant whatever offset each value had. |
moments_as_utc (fix) |
| time |
time(p) |
The same times of day. |
None |
| dates before the year 1000 |
NULL |
MySQL stores years 1000 to 9999, and SQL Server goes back to the year 1. Those values become NULL and the report counts them. |
date_out_of_range (problem) |
Binary#
| In SQL Server |
In MySQL |
Why |
Report line |
| binary, varbinary, image |
binary(n), varbinary(n) and blob types |
Bytes stay bytes. |
None |
| rowversion, timestamp |
blob, empty |
SQL Server sets a row version by itself and SSMS scripts no values for it. |
rowversion_empty (fix) |
JSON, spatial and other types#
| In SQL Server |
In MySQL |
Why |
Report line |
| json (SQL Server 2025) |
json |
The same JSON values, which MySQL's JSON functions read. |
None |
| uniqueidentifier |
char(36) |
The same identifiers, written in lowercase. |
None |
| geometry, geography |
blob with SQL Server's own bytes |
SSMS writes spatial values in SQL Server's serialization, which is kept byte for byte. |
spatial_as_native (fix) |
| xml, sql_variant, hierarchyid, vector |
longtext |
MySQL has no equivalent type; xml and sql_variant keep each value's text and hierarchyid its path, such as /1/2/. |
type_replaced (fix) |
| types IntoSQL doesn't know |
longtext |
Text holds any value; change the type after loading. |
unknown_type (problem) |
Counters and identities#
| In SQL Server |
In MySQL |
Why |
Report line |
| IDENTITY |
AUTO_INCREMENT, continuing after the highest id |
The column that leads the primary key counts; the counter continues after the highest id. |
None |
| IDENTITY columns that don't lead the primary key |
a plain integer |
MySQL counts one column per table, at the start of a key; any other keeps its values without a counter. |
counter_dropped (problem) |
Other pairs#