Convertir MySQL en SQL Server
Déposez un dump de mysqldump, mariadb-dump, mysqlpump, phpMyAdmin ou Adminer, en .sql ou .sql.gz, et téléchargez un script SQL Server avec les mêmes tables, clés, index et données. Chaque valeur que SQL Server ne peut pas contenir telle quelle, et chaque objet qu'il ne reprend pas, est listé dans le rapport.
18 lignes converties, 10 corrections, aucune rejetée
Tables de shop_2024.sqlDump MySQL 8.0.46 · écrit par mysqldump · utf8mb4
customers8 lignes4
7 colonnes id bigint not null name nvarchar(200) not null email nvarchar(150) not null country nvarchar(2) not null is_active bit not null signed_up date created_at datetimeoffset(0) not null orders10 lignes6
9 colonnes id bigint not null customer_id bigint not null status nvarchar(9) not null total decimal(10,2) not null items int not null ordered_at datetime2(0) not null shipped_at datetime2(0) note nvarchar(510) updated_at datetimeoffset(0) not null
-- Written by IntoSQL from a MySQL dump. Load it with: sqlcmd -b -f 65001 -d <database> -i <file>
SET NOCOUNT ON;
SET ANSI_NULLS ON;
SET QUOTED_IDENTIFIER ON;
SET ANSI_PADDING ON;
SET ANSI_WARNINGS ON;
SET ARITHABORT ON;
SET CONCAT_NULL_YIELDS_NULL ON;
SET NUMERIC_ROUNDABORT OFF;
GO
CREATE TABLE [dbo].[customers] (
[id] bigint IDENTITY(1001, 1) NOT NULL,
[name] nvarchar(200) NOT NULL,
[email] nvarchar(150) NOT NULL,
[country] nvarchar(2) DEFAULT N'US' NOT NULL,
[is_active] bit DEFAULT 1 NOT NULL,
[signed_up] date NULL,
[created_at] datetimeoffset(0) DEFAULT SYSDATETIMEOFFSET() NOT NULL,
CONSTRAINT [CK_customers_id] CHECK ([id] >= 0),
CONSTRAINT [PK_customers] PRIMARY KEY ([id])
);
GO
CREATE TABLE [dbo].[orders] (
[id] bigint IDENTITY(5001, 1) NOT NULL,
[customer_id] bigint NOT NULL,
[status] nvarchar(9) DEFAULT N'pending' NOT NULL,
[total] decimal(10,2) NOT NULL,
[items] int DEFAULT 1 NOT NULL,
[ordered_at] datetime2(0) NOT NULL,
[shipped_at] datetime2(0) NULL,
[note] nvarchar(510) NULL,
[updated_at] datetimeoffset(0) DEFAULT SYSDATETIMEOFFSET() NOT NULL,
CONSTRAINT [CK_orders_id] CHECK ([id] >= 0),
CONSTRAINT [CK_orders_customer_id] CHECK ([customer_id] >= 0),
CONSTRAINT [CK_orders_status] CHECK ([status] IN (N'pending', N'paid', N'shipped', N'cancelled', N'')),
CONSTRAINT [CK_orders_items] CHECK ([items] >= 0),
CONSTRAINT [PK_orders] PRIMARY KEY ([id])
);
GO
SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [signed_up], [created_at]) VALUES
(1,N'Ana Martínez',N'ana@example.com',N'MX',1,'2023-01-15','2023-01-15 10:24:00+00:00'),
(2,N'Zoë Müller',N'zoe@example.de',N'DE',1,'2023-02-03','2023-02-03 08:11:42+00:00'),
(3,N'José Peña',N'jose@example.es',N'ES',0,'2023-03-21','2023-03-21 19:05:17+00:00'),
(4,N'李雷',N'lilei@example.cn',N'CN',1,'2023-05-09','2023-05-09 02:40:00+00:00'),
(5,N'Noah O''Brien',N'noah@example.ie',N'IE',1,NULL,'2023-06-30 14:00:00+00:00'),
(6,N'Amélie Laurent',N'amelie@example.fr',N'FR',1,'2024-01-02','2024-01-02 09:30:00+00:00'),
(7,N'Ravi Patel',N'ravi@example.in',N'IN',0,'2024-02-29','2024-02-29 23:59:59+00:00'),
(8,N'Sofia Rossi 🌻',N'sofia@example.it',N'IT',1,'2024-04-12','2024-04-12 12:12:12+00:00');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [status], [total], [items], [ordered_at], [shipped_at], [note], [updated_at]) VALUES
(1,1,N'shipped',129.90,3,'2024-03-01 10:00:00','2024-03-02 16:30:00',NULL,'2024-03-02 16:30:00+00:00'),
(2,2,N'paid',54.00,1,'2024-03-02 11:15:00',NULL,N'Gift wrap 🎁','2024-03-02 11:20:00+00:00'),
(3,1,N'cancelled',12.50,1,'2024-03-03 09:45:00',NULL,N'Customer changed their mind','2024-03-03 10:00:00+00:00'),
(4,4,N'shipped',980.00,12,'2024-03-05 02:10:00','2024-03-07 08:00:00',N'请小心轻放','2024-03-07 08:00:00+00:00'),
(5,5,N'pending',45.75,2,'2024-03-08 17:20:00',NULL,N'Leave at the door; ring twice','2024-03-08 17:20:00+00:00'),
(6,6,N'shipped',310.40,5,'2024-03-10 13:00:00','2024-03-11 09:00:00',N'Fragile: "glass"','2024-03-11 09:00:00+00:00'),
(7,8,N'paid',76.20,2,'2024-03-11 18:45:00',NULL,NULL,'2024-03-11 18:46:00+00:00'),
(8,2,N'',19.99,1,'2024-03-12 08:00:00',NULL,N'Status lost in an old import','2024-03-12 08:00:00+00:00'),
(9,3,N'shipped',64.00,2,'2024-03-14 15:30:00',NULL,N'Shipping date never recorded','2024-03-15 10:00:00+00:00'),
(10,7,N'paid',1499.00,1,'2024-03-15 21:05:00',NULL,N'C:\Users\ravi\invoice.pdf','2024-03-15 21:05:00+00:00');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
-- Indexes, foreign keys, counters and triggers, after the rows.
CREATE UNIQUE INDEX [uq_email] ON [dbo].[customers] ([email]);
CREATE INDEX [idx_customer] ON [dbo].[orders] ([customer_id]);
CREATE INDEX [idx_status_date] ON [dbo].[orders] ([status], [ordered_at]);
ALTER TABLE [dbo].[orders] WITH NOCHECK ADD CONSTRAINT [fk_orders_customer] FOREIGN KEY ([customer_id]) REFERENCES [dbo].[customers] ([id]);
BEGIN TRY ALTER TABLE [dbo].[orders] WITH CHECK CHECK CONSTRAINT [fk_orders_customer]; END TRY BEGIN CATCH PRINT N'Foreign key ' + N'[fk_orders_customer]' + N' has rows without a parent: it stays unchecked, and new rows are checked.'; END CATCH;
DECLARE @next decimal(38,0) = (SELECT MAX([id]) FROM [dbo].[customers]); IF @next IS NOT NULL BEGIN IF @next < 1000 SET @next = 1000; DBCC CHECKIDENT (N'[dbo].[customers]', RESEED, @next) WITH NO_INFOMSGS; END;
GO
EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = N'People who bought at least once', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'customers';
DECLARE @next decimal(38,0) = (SELECT MAX([id]) FROM [dbo].[orders]); IF @next IS NOT NULL BEGIN IF @next < 5000 SET @next = 5000; DBCC CHECKIDENT (N'[dbo].[orders]', RESEED, @next) WITH NO_INFOMSGS; END;
GO
GO
CREATE TRIGGER [dbo].[TR_orders_updated_at_on_update] ON [dbo].[orders] AFTER UPDATE AS
BEGIN
SET NOCOUNT ON;
IF NOT UPDATE([updated_at])
UPDATE x SET [updated_at] = SYSDATETIMEOFFSET() FROM [dbo].[orders] AS x JOIN inserted AS i ON x.[id] = i.[id];
END;
GO
GO
Corrections
- "id" de customers est non signée ; elle est donc devenue bigint avec un CHECK qui interdit les valeurs négatives.
- "name" de customers contient des caractères que SQL Server compte double, comme les emoji ; elle est donc en nvarchar(200).
- "signed_up" de customers accepte maintenant NULL : certaines de ses valeurs ne pouvaient pas être stockées et sont NULL.
- La valeur par défaut de "signed_up" dans customers, 0000‑00‑00, n'est pas une date acceptée par SQL Server ; la colonne n'a donc pas de valeur par défaut.
- "customer_id" de orders est non signée ; elle est donc devenue bigint avec un CHECK qui interdit les valeurs négatives.
- "id" de orders est non signée ; elle est donc devenue bigint avec un CHECK qui interdit les valeurs négatives.
- "items" de orders est non signée ; elle est donc devenue int avec un CHECK qui interdit les valeurs négatives.
- "note" de orders contient des caractères que SQL Server compte double, comme les emoji ; elle est donc en nvarchar(510).
- 1 ligne de "status" dans orders contient la valeur vide que MySQL stocke pour les entrées invalides ; la contrainte CHECK de ses valeurs l'autorise.
- "updated_at" de orders passe à l'heure actuelle à chaque mise à jour ; dans SQL Server, un déclencheur s'en charge.
À vérifier
- 1 valeur dans "signed_up" de customers est une date zéro ou impossible, comme 0000‑00‑00, que SQL Server ne peut pas stocker ; elle est donc NULL. Si ces dates ont un sens, remplacez-les dans la source par de vraies dates avant le dump.
- 1 valeur dans "shipped_at" de orders est une date zéro ou impossible, comme 0000‑00‑00 00:00:00, que SQL Server ne peut pas stocker ; elle est donc NULL. Si ces dates ont un sens, remplacez-les dans la source par de vraies dates avant le dump.
Votre fichier est converti sur cet ordinateur et n'est jamais envoyé.
Autres exemples :
Ce qui change de MySQL à SQL Server
Chaque ligne est une règle appliquée par le convertisseur, avec la ligne de rapport qu'il écrit quand la règle change quelque chose dans vos données.
TINYINT(1), BOOL
bit si chaque valeur vaut 0 ou 1, sinon smallint
Le BOOL de MySQL est un TINYINT(1) qui peut contenir tout nombre de -128 à 127. Une colonne qui ne contient que 0 et 1 devient bit ; une colonne qui contient 2 ou -1 reste un nombre, pour qu'aucune valeur ne change de sens.
Ligne du rapport: bool_kept_numeric
UNSIGNED integers
TINYINT UNSIGNED devient tinyint ; les autres, l'entier immédiatement plus large avec un CHECK qui interdit les négatifs, BIGINT UNSIGNED devient bigint si chaque valeur y tient, sinon decimal(38,0)
SQL Server n'a pas d'entiers non signés sauf tinyint, qui va de 0 à 255. Un type plus large contient toute la plage non signée, et la contrainte CHECK écarte les valeurs négatives comme le faisait MySQL.
Ligne du rapport: unsigned_widened
ZEROFILL and display widths
supprimé
Le remplissage par des zéros est une façon d'afficher un nombre, pas une partie du nombre. Les nombres sont conservés ; formatez-les à la lecture si le remplissage compte.
Ligne du rapport: zerofill_dropped
FLOAT(M,D)
real ou float, sans l'échelle
Les flottants SQL Server n'ont pas d'échelle fixe. Les valeurs stockées sont copiées telles quelles.
Ligne du rapport: float_scale_dropped
DECIMAL(p,s)
decimal(p,s) jusqu'à 38 chiffres ; nvarchar au-delà
Le decimal de SQL Server contient 38 chiffres. Les décimaux plus larges sont gardés en texte pour que chaque chiffre reste exact.
Ligne du rapport: decimal_as_text
BIT(1), BIT(n)
bit ; bigint jusqu'à 63 bits ; decimal(20,0) pour BIT(64)
Un seul bit est un oui ou un non ; les champs de bits plus larges sont stockés comme le nombre que forment leurs bits.
zero, partial or impossible dates (0000-00-00, 2024-02-30)
NULL
SQL Server ne stocke que de vraies dates du calendrier. MySQL garde les dates zéro et impossibles quand son mode SQL les autorise ; elles deviennent NULL et le rapport les compte.
Ligne du rapport: invalid_date_null
NOT NULL columns with values that become NULL
NOT NULL retiré
Une colonne dont des valeurs ont dû devenir NULL ne peut pas garder NOT NULL, sinon le chargement s'arrêterait.
Ligne du rapport: not_null_relaxed
DEFAULT '0000-00-00'
aucune valeur par défaut
Une valeur par défaut que SQL Server ne peut pas stocker est omise plutôt que remplacée par une date inventée.
Ligne du rapport: zero_date_default
TIME
time si chaque valeur tient dans une journée, sinon nvarchar
Le TIME de MySQL est une durée de -838:59:59 à 838:59:59 ; le time de SQL Server est une heure du jour. Une colonne avec des valeurs plus longues ou négatives les garde en texte.
Ligne du rapport: time_as_interval
YEAR
smallint avec un CHECK de sa plage
SQL Server n'a pas de type année ; le CHECK garde les mêmes valeurs que MySQL autorise.
CHAR(n), VARCHAR(n)
nvarchar(n)
nvarchar contient tous les caractères sur chaque version prise en charge, et MySQL renvoie les valeurs CHAR sans espaces de fin, telles que nvarchar les garde.
text with characters past U+FFFF (emoji) in VARCHAR(n)
nvarchar(2n), ou nvarchar(max) au-delà de 4000
nvarchar compte en unités UTF-16 et un emoji en prend deux ; la colonne a donc la place pour chaque valeur.
Ligne du rapport: text_length_widened
DATETIME
datetime2
Un DATETIME est une date et une heure locales, sans fuseau horaire, comme datetime2.
TIMESTAMP
datetimeoffset dans le fuseau horaire indiqué par le dump, UTC s'il n'en indique aucun
Un TIMESTAMP est un instant. Les dumps indiquent le fuseau dans lequel ils l'ont écrit (mysqldump écrit en UTC) ; sinon, les valeurs sont lues en UTC et le rapport le signale.
Ligne du rapport: timestamp_zone_assumed
ENUM
nvarchar avec un CHECK de ses valeurs
Un texte avec une contrainte CHECK garde les mêmes valeurs.
ENUM holding '' (MySQL's error value)
la valeur vide autorisée par le CHECK
MySQL stocke une chaîne vide quand une valeur invalide entre dans un ENUM avec un mode SQL permissif. Ces lignes sont conservées et la contrainte CHECK les autorise.
Ligne du rapport: enum_invalid_value
ENUM holding values outside its list
pas de CHECK
Les valeurs absentes de la liste feraient échouer la contrainte CHECK, qui n'est donc pas créée.
Ligne du rapport: enum_check_skipped
SET
nvarchar tel que MySQL l'écrit ('a,b')
SQL Server n'a pas de tableaux ; le texte est celui que MySQL renvoie.
JSON
nvarchar(max)
Les fonctions JSON de SQL Server lisent le JSON depuis du texte. Un CHECK ISJSON refuserait avant SQL Server 2022 des valeurs scalaires comme 1 ou "x", que MySQL garde.
NUL bytes in text
conservé
nvarchar peut contenir un caractère NUL, donc la valeur est copiée telle quelle.
text that isn't valid in its character set
les octets invalides deviennent le caractère de remplacement
Le texte doit être lu comme des caractères pour être écrit en nvarchar.
Ligne du rapport: invalid_utf8_replaced
text decoded twice (ñ)
copié tel quel
Le dump contient exactement ces caractères, ils sont donc copiés ; le rapport les signale.
Ligne du rapport: mojibake_suspected
AUTO_INCREMENT
IDENTITY, avec le compteur placé après les identifiants copiés
Les identifiants copiés se chargent avec IDENTITY_INSERT, et le compteur reprend après le plus élevé ou après l'AUTO_INCREMENT du dump, selon le plus grand.
MyISAM AUTO_INCREMENT on the second column of a key
un seul compteur pour la table
MyISAM compte par groupe de la première colonne de la clé ; SQL Server a un compteur par table.
Ligne du rapport: myisam_group_autoincrement
ON UPDATE CURRENT_TIMESTAMP
un déclencheur AFTER UPDATE
Le déclencheur met la colonne à l'heure actuelle quand une mise à jour ne la définit pas. Il fait la jointure sur la clé primaire, donc la table doit en avoir une.
Ligne du rapport: on_update_trigger
ON UPDATE CURRENT_TIMESTAMP on a table without a primary key
non reporté
Le déclencheur trouve les lignes mises à jour par leur clé primaire ; sans clé primaire, il ne peut pas.
Ligne du rapport: on_update_without_key
generated columns
colonnes calculées, PERSISTED quand la source les stocke
SQL Server les calcule des deux mêmes façons.
generated columns with functions SQL Server lacks
une colonne simple
Une formule qui ne peut pas être écrite pour SQL Server laisse une colonne simple et une ligne dans le rapport.
Ligne du rapport: generated_not_translated
INVISIBLE columns
colonnes ordinaires
SQL Server n'a pas de colonnes invisibles.
Ligne du rapport: invisible_column
CHECK constraints
traduites, en ligne dans CREATE TABLE
Les CHECK en ligne sont vérifiés au chargement de chaque ligne.
CHECK constraints with functions SQL Server lacks
non créée
Une contrainte CHECK qui ne peut pas être écrite pour SQL Server est omise et signalée.
Ligne du rapport: check_skipped
CHECK ... NOT ENFORCED
non créée
MySQL garde ces contraintes CHECK sans les appliquer, donc les lignes peuvent les enfreindre.
Ligne du rapport: check_not_enforced
defaults with functions SQL Server lacks
aucune valeur par défaut
Une valeur par défaut qui ne peut pas être écrite pour SQL Server est omise et signalée.
Ligne du rapport: default_not_translated
keys and indexes on a prefix, c(20)
un index sur la colonne entière
SQL Server indexe des colonnes entières ; une clé unique sur un préfixe est aussi unique sur la colonne entière, donc chaque ligne se charge.
Ligne du rapport: prefix_whole_column
FULLTEXT indexes
non créée
La recherche plein texte de SQL Server demande un catalogue et ses propres requêtes.
Ligne du rapport: fulltext_not_created
SPATIAL indexes
non créée
Un index spatial sur une colonne geometry demande une zone englobante que le dump n'indique pas.
Ligne du rapport: spatial_index_not_created
functional indexes, and indexes on columns of unlimited length
non créé
SQL Server n'indexe ni les expressions ni les colonnes nvarchar(max) et varbinary(max).
Ligne du rapport: index_skipped
foreign keys
après les données WITH NOCHECK, puis vérifiée avec un avertissement sur les orphelins
Les dumps se chargent avec FOREIGN_KEY_CHECKS=0 et MyISAM ne vérifie jamais, donc les lignes sans parent sont fréquentes. La clé est créée d'abord et vérifiée en dernier ; des orphelins la laissent non vérifiée avec un avertissement au lieu d'arrêter le chargement.
ON DELETE or ON UPDATE that cascades in a cycle or along a second path
NO ACTION
SQL Server refuse les cascades qui pourraient atteindre une table deux fois ; MySQL les autorise.
Ligne du rapport: foreign_key_action_dropped
foreign keys to columns without a unique key
non créée
SQL Server exige une clé primaire ou un index unique sans NULL sur les colonnes référencées ; InnoDB non.
Ligne du rapport: foreign_key_skipped
table and column names
tels qu'écrits ; renommés s'ils ne diffèrent que par la casse
Les noms SQL Server ignorent la casse avec la collation habituelle.
Ligne du rapport: identifier_renamed
names over 116 characters
raccourci
Les noms SQL Server font 128 caractères au plus, dont certains pour les numéros qui distinguent les noms.
Ligne du rapport: name_shortened
GEOMETRY, POINT, POLYGON...
geometry, avec le SRID de chaque valeur
Le type geometry propre à SQL Server garde chaque forme et son système de référence spatiale.
INET4, INET6, UUID (MariaDB)
nvarchar(39), uniqueidentifier
uniqueidentifier est l'UUID de SQL Server ; les adresses sont gardées en texte.
BINARY, VARBINARY, BLOB
binary, varbinary, varbinary(max)
Les octets restent des octets.
PARTITION BY
une seule table
Les lignes sont les mêmes ; partitionnez à nouveau la table dans SQL Server si besoin.
Ligne du rapport: partitions_dropped
WITH SYSTEM VERSIONING (MariaDB)
une table avec les lignes actuelles
Un dump ne contient que les lignes actuelles.
Ligne du rapport: system_versioning_dropped
MyISAM, MEMORY and other engines
une table ordinaire
SQL Server a un seul moteur de tables.
Ligne du rapport: engine_dropped
views, triggers, procedures, functions and events
listés dans le rapport
Leur code est écrit dans le langage de MySQL ; ils sont donc listés pour que vous les recréiez.
Ligne du rapport: not_converted_objects
dumps without CREATE TABLE
types déduits des valeurs
Un dump fait avec --no-create-info ne contient que des lignes, donc les types viennent des valeurs.
Ligne du rapport: no_schema
geometries in a dump without CREATE TABLE
geometry
Le format de géométrie de MySQL est reconnu à partir des valeurs.
_ci collations
la collation de la base, en général insensible à la casse
SQL Server compare le texte sans tenir compte de la casse avec sa collation habituelle, comme le _ci de MySQL.
SET NAMES utf8 from utf8mb4 tables
converti, avec un avertissement
Le mysqldump de MySQL 5.x écrit par défaut en utf8 sur 3 octets et remplace chaque emoji par un point d'interrogation avant qu'un convertisseur ne voie le fichier.
Ligne du rapport: dump_lost_four_byte_chars
dumps without SET NAMES whose text isn't UTF-8
lu comme Latin-1 (Windows-1252)
Le latin1 de MySQL est le Windows-1252, l'encodage habituel de ces dumps.
Ligne du rapport: charset_guessed
sjis, cp932, gbk, big5 dumps
lu comme UTF-8, avec un avertissement
Ces encodages ne sont pas encore décodés.
Ligne du rapport: unsupported_charset
UNHEX('..'), CONVERT(b'..', UNSIGNED), CONVERT(".." USING x), ST_GeomFromText('..') in rows
évaluées
Certains outils de dump écrivent les valeurs sous forme de ces appels ; ils sont lus comme les valeurs qu'ils produisent, le WKT géographique étant remis avec la longitude en premier.
other expressions in rows
NULL
Un convertisseur qui n'exécute pas de base de données ne peut pas les évaluer.
Ligne du rapport: expression_value
DEFAULT in VALUES
la valeur par défaut de la colonne
Une valeur par défaut littérale est copiée dans la ligne.
Ligne du rapport: default_keyword_filled
DEFAULT in VALUES without a literal default
NULL
Il n'y a aucune valeur à copier.
Ligne du rapport: default_keyword_null
REPLACE and INSERT IGNORE
lignes simples
Un dump a une ligne par clé, donc les lignes sont les mêmes.
Ligne du rapport: replace_as_insert
types IntoSQL doesn't know
nvarchar(max)
Le texte contient n'importe quelle valeur ; changez le type après le chargement.
Ligne du rapport: unknown_type
values that don't fit their column
NULL
Un dump endommagé ou écrit à la main peut contenir des valeurs que sa colonne n'accepte pas ; elles deviennent NULL pour que le reste se charge.
Ligne du rapport: invalid_value_null
unreadable geometries
NULL
Des octets qui ne forment pas une géométrie ne peuvent pas être stockés comme telle.
Ligne du rapport: bad_geometry
CREATE SEQUENCE (MariaDB)
CREATE SEQUENCE ... AS bigint, avec sa prochaine valeur
SQL Server a des séquences avec les mêmes options ; chacune reprend là où le dump l'a laissée.
VECTOR(n) (MariaDB 11.7+)
nvarchar(max) avec les flottants en tableau JSON
Seul SQL Server 2025 a un type vector ; un tableau JSON garde chaque flottant dans toutes les versions.
Ligne du rapport: type_replaced
| Dans MySQL | Dans SQL Server | Ligne du rapport |
|---|---|---|
| TINYINT(1), BOOL | bit si chaque valeur vaut 0 ou 1, sinon smallintLe BOOL de MySQL est un TINYINT(1) qui peut contenir tout nombre de -128 à 127. Une colonne qui ne contient que 0 et 1 devient bit ; une colonne qui contient 2 ou -1 reste un nombre, pour qu'aucune valeur ne change de sens. | bool_kept_numeric |
| UNSIGNED integers | TINYINT UNSIGNED devient tinyint ; les autres, l'entier immédiatement plus large avec un CHECK qui interdit les négatifs, BIGINT UNSIGNED devient bigint si chaque valeur y tient, sinon decimal(38,0)SQL Server n'a pas d'entiers non signés sauf tinyint, qui va de 0 à 255. Un type plus large contient toute la plage non signée, et la contrainte CHECK écarte les valeurs négatives comme le faisait MySQL. | unsigned_widened |
| ZEROFILL and display widths | suppriméLe remplissage par des zéros est une façon d'afficher un nombre, pas une partie du nombre. Les nombres sont conservés ; formatez-les à la lecture si le remplissage compte. | zerofill_dropped |
| FLOAT(M,D) | real ou float, sans l'échelleLes flottants SQL Server n'ont pas d'échelle fixe. Les valeurs stockées sont copiées telles quelles. | float_scale_dropped |
| DECIMAL(p,s) | decimal(p,s) jusqu'à 38 chiffres ; nvarchar au-delàLe decimal de SQL Server contient 38 chiffres. Les décimaux plus larges sont gardés en texte pour que chaque chiffre reste exact. | decimal_as_text |
| BIT(1), BIT(n) | bit ; bigint jusqu'à 63 bits ; decimal(20,0) pour BIT(64)Un seul bit est un oui ou un non ; les champs de bits plus larges sont stockés comme le nombre que forment leurs bits. | |
| zero, partial or impossible dates (0000-00-00, 2024-02-30) | NULLSQL Server ne stocke que de vraies dates du calendrier. MySQL garde les dates zéro et impossibles quand son mode SQL les autorise ; elles deviennent NULL et le rapport les compte. | invalid_date_null |
| NOT NULL columns with values that become NULL | NOT NULL retiréUne colonne dont des valeurs ont dû devenir NULL ne peut pas garder NOT NULL, sinon le chargement s'arrêterait. | not_null_relaxed |
| DEFAULT '0000-00-00' | aucune valeur par défautUne valeur par défaut que SQL Server ne peut pas stocker est omise plutôt que remplacée par une date inventée. | zero_date_default |
| TIME | time si chaque valeur tient dans une journée, sinon nvarcharLe TIME de MySQL est une durée de -838:59:59 à 838:59:59 ; le time de SQL Server est une heure du jour. Une colonne avec des valeurs plus longues ou négatives les garde en texte. | time_as_interval |
| YEAR | smallint avec un CHECK de sa plageSQL Server n'a pas de type année ; le CHECK garde les mêmes valeurs que MySQL autorise. | |
| CHAR(n), VARCHAR(n) | nvarchar(n)nvarchar contient tous les caractères sur chaque version prise en charge, et MySQL renvoie les valeurs CHAR sans espaces de fin, telles que nvarchar les garde. | |
| text with characters past U+FFFF (emoji) in VARCHAR(n) | nvarchar(2n), ou nvarchar(max) au-delà de 4000nvarchar compte en unités UTF-16 et un emoji en prend deux ; la colonne a donc la place pour chaque valeur. | text_length_widened |
| DATETIME | datetime2Un DATETIME est une date et une heure locales, sans fuseau horaire, comme datetime2. | |
| TIMESTAMP | datetimeoffset dans le fuseau horaire indiqué par le dump, UTC s'il n'en indique aucunUn TIMESTAMP est un instant. Les dumps indiquent le fuseau dans lequel ils l'ont écrit (mysqldump écrit en UTC) ; sinon, les valeurs sont lues en UTC et le rapport le signale. | timestamp_zone_assumed |
| ENUM | nvarchar avec un CHECK de ses valeursUn texte avec une contrainte CHECK garde les mêmes valeurs. | |
| ENUM holding '' (MySQL's error value) | la valeur vide autorisée par le CHECKMySQL stocke une chaîne vide quand une valeur invalide entre dans un ENUM avec un mode SQL permissif. Ces lignes sont conservées et la contrainte CHECK les autorise. | enum_invalid_value |
| ENUM holding values outside its list | pas de CHECKLes valeurs absentes de la liste feraient échouer la contrainte CHECK, qui n'est donc pas créée. | enum_check_skipped |
| SET | nvarchar tel que MySQL l'écrit ('a,b')SQL Server n'a pas de tableaux ; le texte est celui que MySQL renvoie. | |
| JSON | nvarchar(max)Les fonctions JSON de SQL Server lisent le JSON depuis du texte. Un CHECK ISJSON refuserait avant SQL Server 2022 des valeurs scalaires comme 1 ou "x", que MySQL garde. | |
| NUL bytes in text | conservénvarchar peut contenir un caractère NUL, donc la valeur est copiée telle quelle. | |
| text that isn't valid in its character set | les octets invalides deviennent le caractère de remplacementLe texte doit être lu comme des caractères pour être écrit en nvarchar. | invalid_utf8_replaced |
| text decoded twice (ñ) | copié tel quelLe dump contient exactement ces caractères, ils sont donc copiés ; le rapport les signale. | mojibake_suspected |
| AUTO_INCREMENT | IDENTITY, avec le compteur placé après les identifiants copiésLes identifiants copiés se chargent avec IDENTITY_INSERT, et le compteur reprend après le plus élevé ou après l'AUTO_INCREMENT du dump, selon le plus grand. | |
| MyISAM AUTO_INCREMENT on the second column of a key | un seul compteur pour la tableMyISAM compte par groupe de la première colonne de la clé ; SQL Server a un compteur par table. | myisam_group_autoincrement |
| ON UPDATE CURRENT_TIMESTAMP | un déclencheur AFTER UPDATELe déclencheur met la colonne à l'heure actuelle quand une mise à jour ne la définit pas. Il fait la jointure sur la clé primaire, donc la table doit en avoir une. | on_update_trigger |
| ON UPDATE CURRENT_TIMESTAMP on a table without a primary key | non reportéLe déclencheur trouve les lignes mises à jour par leur clé primaire ; sans clé primaire, il ne peut pas. | on_update_without_key |
| generated columns | colonnes calculées, PERSISTED quand la source les stockeSQL Server les calcule des deux mêmes façons. | |
| generated columns with functions SQL Server lacks | une colonne simpleUne formule qui ne peut pas être écrite pour SQL Server laisse une colonne simple et une ligne dans le rapport. | generated_not_translated |
| INVISIBLE columns | colonnes ordinairesSQL Server n'a pas de colonnes invisibles. | invisible_column |
| CHECK constraints | traduites, en ligne dans CREATE TABLELes CHECK en ligne sont vérifiés au chargement de chaque ligne. | |
| CHECK constraints with functions SQL Server lacks | non crééeUne contrainte CHECK qui ne peut pas être écrite pour SQL Server est omise et signalée. | check_skipped |
| CHECK ... NOT ENFORCED | non crééeMySQL garde ces contraintes CHECK sans les appliquer, donc les lignes peuvent les enfreindre. | check_not_enforced |
| defaults with functions SQL Server lacks | aucune valeur par défautUne valeur par défaut qui ne peut pas être écrite pour SQL Server est omise et signalée. | default_not_translated |
| keys and indexes on a prefix, c(20) | un index sur la colonne entièreSQL Server indexe des colonnes entières ; une clé unique sur un préfixe est aussi unique sur la colonne entière, donc chaque ligne se charge. | prefix_whole_column |
| FULLTEXT indexes | non crééeLa recherche plein texte de SQL Server demande un catalogue et ses propres requêtes. | fulltext_not_created |
| SPATIAL indexes | non crééeUn index spatial sur une colonne geometry demande une zone englobante que le dump n'indique pas. | spatial_index_not_created |
| functional indexes, and indexes on columns of unlimited length | non crééSQL Server n'indexe ni les expressions ni les colonnes nvarchar(max) et varbinary(max). | index_skipped |
| foreign keys | après les données WITH NOCHECK, puis vérifiée avec un avertissement sur les orphelinsLes dumps se chargent avec FOREIGN_KEY_CHECKS=0 et MyISAM ne vérifie jamais, donc les lignes sans parent sont fréquentes. La clé est créée d'abord et vérifiée en dernier ; des orphelins la laissent non vérifiée avec un avertissement au lieu d'arrêter le chargement. | |
| ON DELETE or ON UPDATE that cascades in a cycle or along a second path | NO ACTIONSQL Server refuse les cascades qui pourraient atteindre une table deux fois ; MySQL les autorise. | foreign_key_action_dropped |
| foreign keys to columns without a unique key | non crééeSQL Server exige une clé primaire ou un index unique sans NULL sur les colonnes référencées ; InnoDB non. | foreign_key_skipped |
| table and column names | tels qu'écrits ; renommés s'ils ne diffèrent que par la casseLes noms SQL Server ignorent la casse avec la collation habituelle. | identifier_renamed |
| names over 116 characters | raccourciLes noms SQL Server font 128 caractères au plus, dont certains pour les numéros qui distinguent les noms. | name_shortened |
| GEOMETRY, POINT, POLYGON... | geometry, avec le SRID de chaque valeurLe type geometry propre à SQL Server garde chaque forme et son système de référence spatiale. | |
| INET4, INET6, UUID (MariaDB) | nvarchar(39), uniqueidentifieruniqueidentifier est l'UUID de SQL Server ; les adresses sont gardées en texte. | |
| BINARY, VARBINARY, BLOB | binary, varbinary, varbinary(max)Les octets restent des octets. | |
| PARTITION BY | une seule tableLes lignes sont les mêmes ; partitionnez à nouveau la table dans SQL Server si besoin. | partitions_dropped |
| WITH SYSTEM VERSIONING (MariaDB) | une table avec les lignes actuellesUn dump ne contient que les lignes actuelles. | system_versioning_dropped |
| MyISAM, MEMORY and other engines | une table ordinaireSQL Server a un seul moteur de tables. | engine_dropped |
| views, triggers, procedures, functions and events | listés dans le rapportLeur code est écrit dans le langage de MySQL ; ils sont donc listés pour que vous les recréiez. | not_converted_objects |
| dumps without CREATE TABLE | types déduits des valeursUn dump fait avec --no-create-info ne contient que des lignes, donc les types viennent des valeurs. | no_schema |
| geometries in a dump without CREATE TABLE | geometryLe format de géométrie de MySQL est reconnu à partir des valeurs. | |
| _ci collations | la collation de la base, en général insensible à la casseSQL Server compare le texte sans tenir compte de la casse avec sa collation habituelle, comme le _ci de MySQL. | |
| SET NAMES utf8 from utf8mb4 tables | converti, avec un avertissementLe mysqldump de MySQL 5.x écrit par défaut en utf8 sur 3 octets et remplace chaque emoji par un point d'interrogation avant qu'un convertisseur ne voie le fichier. | dump_lost_four_byte_chars |
| dumps without SET NAMES whose text isn't UTF-8 | lu comme Latin-1 (Windows-1252)Le latin1 de MySQL est le Windows-1252, l'encodage habituel de ces dumps. | charset_guessed |
| sjis, cp932, gbk, big5 dumps | lu comme UTF-8, avec un avertissementCes encodages ne sont pas encore décodés. | unsupported_charset |
| UNHEX('..'), CONVERT(b'..', UNSIGNED), CONVERT(".." USING x), ST_GeomFromText('..') in rows | évaluéesCertains outils de dump écrivent les valeurs sous forme de ces appels ; ils sont lus comme les valeurs qu'ils produisent, le WKT géographique étant remis avec la longitude en premier. | |
| other expressions in rows | NULLUn convertisseur qui n'exécute pas de base de données ne peut pas les évaluer. | expression_value |
| DEFAULT in VALUES | la valeur par défaut de la colonneUne valeur par défaut littérale est copiée dans la ligne. | default_keyword_filled |
| DEFAULT in VALUES without a literal default | NULLIl n'y a aucune valeur à copier. | default_keyword_null |
| REPLACE and INSERT IGNORE | lignes simplesUn dump a une ligne par clé, donc les lignes sont les mêmes. | replace_as_insert |
| types IntoSQL doesn't know | nvarchar(max)Le texte contient n'importe quelle valeur ; changez le type après le chargement. | unknown_type |
| values that don't fit their column | NULLUn dump endommagé ou écrit à la main peut contenir des valeurs que sa colonne n'accepte pas ; elles deviennent NULL pour que le reste se charge. | invalid_value_null |
| unreadable geometries | NULLDes octets qui ne forment pas une géométrie ne peuvent pas être stockés comme telle. | bad_geometry |
| CREATE SEQUENCE (MariaDB) | CREATE SEQUENCE ... AS bigint, avec sa prochaine valeurSQL Server a des séquences avec les mêmes options ; chacune reprend là où le dump l'a laissée. | |
| VECTOR(n) (MariaDB 11.7+) | nvarchar(max) avec les flottants en tableau JSONSeul SQL Server 2025 a un type vector ; un tableau JSON garde chaque flottant dans toutes les versions. | type_replaced |
Charger le script dans SQL Server
Le script crée les tables, copie les lignes, puis ajoute les clés, les index et les clés étrangères ; il se charge donc vite et s'arrête à la première erreur.
sqlcmd -b -f 65001 -S localhost -d mydb -i mysql.sql_server.sqlLes clés étrangères sont ajoutées WITH NOCHECK, puis vérifiées. Si une ligne pointe vers une ligne qui n'existe pas, le script indique quelle contrainte et la laisse non vérifiée, au lieu d'échouer à mi-chemin.
Pour un gros dump, exécutez sqlcmd sur la machine du serveur. Chaque lot de 1000 lignes au plus est validé à part, donc le journal des transactions reste petit.
Faire le dump MySQL pour un meilleur résultat
Le convertisseur lit ce que contient le dump. Ces options y gardent davantage de vos données :
- --default-character-set=utf8mb4 garde les emoji et autres caractères sur 4 octets, qu'un dump utf8 perd avant que le convertisseur ne le voie.
- --hex-blob écrit les colonnes binaires en hexadécimal, ce qui résiste aux copies entre systèmes.
- --routines --triggers --events ajoutent ces objets au dump, pour que le rapport puisse les lister.
Ce qui n'est pas converti
Les vues, déclencheurs, procédures stockées, fonctions et événements sont écrits dans le langage propre à chaque base de données. Ils sont listés par nom dans le rapport, jamais supprimés en silence, pour que vous puissiez les réécrire pour SQL Server.
Questions sur MySQL vers SQL Server
Pas de réponse ici ? Écrivez-nous depuis la page de contact, une personne vous répond. Page de contact
Mon dump est-il envoyé ?
Non. Le convertisseur s'exécute dans votre navigateur et lit le dump depuis votre disque par morceaux ; il ne quitte donc jamais votre ordinateur. L'application de bureau et la ligne de commande convertissent aussi sur votre ordinateur.
Quelle taille peut avoir le dump ?
Le convertisseur ne garde jamais tout le dump en mémoire : il lit le fichier deux fois, par plages, et écrit le script au fur et à mesure. Les dumps de plusieurs gigaoctets se convertissent dans le navigateur, dans l'application de bureau et avec la ligne de commande.
Lit-il les dumps MariaDB ?
Oui. Les dumps de mariadb-dump et de MariaDB 10.3 à 12 se convertissent de la même façon, y compris les colonnes INET6, INET4 et UUID de MariaDB.
Que deviennent les dates 0000-00-00 ?
SQL Server n'a pas de date zéro ; elles deviennent donc NULL et la colonne accepte NULL. Le rapport indique combien il y en avait dans chaque colonne.
Les valeurs AUTO_INCREMENT sont-elles conservées ?
Oui. Chaque colonne AUTO_INCREMENT devient une colonne IDENTITY, chaque ligne garde son identifiant, et le prochain identifiant reprend après le plus élevé, ou après l'AUTO_INCREMENT de la table s'il est plus grand.
TINYINT(1) devient-il boolean ?
Elle devient bit seulement si chaque valeur de la colonne vaut 0 ou 1. Si elle contient d'autres nombres, comme 2 ou -1, elle reste un nombre et le rapport explique pourquoi ; aucune valeur ne devient 1 par accident.
Et les procédures stockées et les déclencheurs ?
Ils sont listés par nom dans le rapport et ne sont pas convertis, car chaque base de données les écrit dans son propre langage. ON UPDATE CURRENT_TIMESTAMP est l'exception : il devient un déclencheur SQL Server.
Sur quelles versions de SQL Server le script se charge-t-il ?
SQL Server 2017 à 2025. Le même script se charge sur chacune, et s'arrête à la première erreur en cas de problème.