Конвертация MariaDB в SQL Server
Перетащите дамп из mariadb-dump, mysqldump, phpMyAdmin или Adminer в формате .sql или .sql.gz и скачайте скрипт SQL Server с теми же таблицами, ключами, индексами и данными. Каждое значение, которое SQL Server не может хранить как есть, и каждый объект, который он не переносит, указаны в отчете.
18 строк конвертировано, 10 исправлений, ни одна не отклонена
Таблицы в shop_2024_mariadb.sqlДамп MariaDB 11.8.9-MariaDB-ubu2404 · создан программой mariadb-dump · utf8mb4
customers8 строк4
8 столбцов 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 last_ip nvarchar(39) orders10 строк6
12 столбцов 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) order_ref uniqueidentifier not null invoice int not null details nvarchar(max) 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 SEQUENCE [dbo].[invoice_numbers] AS bigint START WITH 2000 INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775806;
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,
[last_ip] nvarchar(39) 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,
[order_ref] uniqueidentifier NOT NULL,
[invoice] int DEFAULT (NEXT VALUE FOR [dbo].[invoice_numbers]) NOT NULL,
[details] nvarchar(max) 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], [last_ip]) VALUES
(1,N'Ana Martínez',N'ana@example.com',N'MX',1,'2023-01-15','2023-01-15 10:24:00+00:00',N'::ffff:203.0.113.7'),
(2,N'Zoë Müller',N'zoe@example.de',N'DE',1,'2023-02-03','2023-02-03 08:11:42+00:00',N'2001:db8::1'),
(3,N'José Peña',N'jose@example.es',N'ES',0,'2023-03-21','2023-03-21 19:05:17+00:00',NULL),
(4,N'李雷',N'lilei@example.cn',N'CN',1,'2023-05-09','2023-05-09 02:40:00+00:00',N'::ffff:198.51.100.23'),
(5,N'Noah O''Brien',N'noah@example.ie',N'IE',1,NULL,'2023-06-30 14:00:00+00:00',NULL),
(6,N'Amélie Laurent',N'amelie@example.fr',N'FR',1,'2024-01-02','2024-01-02 09:30:00+00:00',N'2001:db8:85a3::8a2e:370:7334'),
(7,N'Ravi Patel',N'ravi@example.in',N'IN',0,'2024-02-29','2024-02-29 23:59:59+00:00',N'::ffff:192.0.2.200'),
(8,N'Sofia Rossi 🌻',N'sofia@example.it',N'IT',1,'2024-04-12','2024-04-12 12:12:12+00:00',NULL);
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], [order_ref], [invoice], [details], [updated_at]) VALUES
(1,1,N'shipped',129.90,3,'2024-03-01 10:00:00','2024-03-02 16:30:00',NULL,N'0b7a4c2e-3f1d-4e8a-9c55-1a2b3c4d5e6f',1000,N'{"gift": false}','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 🎁',N'1c8b5d3f-4a2e-4f9b-8d66-2b3c4d5e6f70',1001,N'{"gift": true, "wrap": "red"}','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',N'2d9c6e4a-5b3f-4a0c-9e77-3c4d5e6f7081',1002,NULL,'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'请小心轻放',N'3e0d7f5b-6c4a-4b1d-8f88-4d5e6f708192',1003,N'{"fragile": true}','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',N'4f1e806c-7d5b-4c2e-9a99-5e6f708192a3',1004,NULL,'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"',N'50f2917d-8e6c-4d3f-8baa-6f708192a3b4',1005,N'{"fragile": true}','2024-03-11 09:00:00+00:00'),
(7,8,N'paid',76.20,2,'2024-03-11 18:45:00',NULL,NULL,N'6103a28e-9f7d-4e40-9cbb-708192a3b4c5',1006,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',N'7214b39f-a08e-4f51-8dcc-8192a3b4c5d6',1007,NULL,'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',N'8325c4a0-b19f-4062-9edd-92a3b4c5d6e7',1008,N'{"parcels": [1, 2]}','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',N'9436d5b1-c2a0-4173-8fee-a3b4c5d6e7f8',1009,NULL,'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
Исправления
- Столбец "id" таблицы customers беззнаковый, поэтому он стал bigint с проверкой, что значение не отрицательное.
- "name" таблицы customers содержит символы, которые SQL Server считает дважды, например эмодзи, поэтому тип nvarchar(200).
- Столбец "signed_up" таблицы customers теперь допускает NULL: часть его значений нельзя было сохранить, и они записаны как NULL.
- Значение по умолчанию столбца "signed_up" таблицы customers, 0000‑00‑00, не является датой, которую принимает SQL Server, поэтому у столбца его нет.
- Столбец "customer_id" таблицы orders беззнаковый, поэтому он стал bigint с проверкой, что значение не отрицательное.
- Столбец "id" таблицы orders беззнаковый, поэтому он стал bigint с проверкой, что значение не отрицательное.
- Столбец "items" таблицы orders беззнаковый, поэтому он стал int с проверкой, что значение не отрицательное.
- "note" таблицы orders содержит символы, которые SQL Server считает дважды, например эмодзи, поэтому тип nvarchar(510).
- В 1 строке столбца "status" таблицы orders пустое значение, которое MySQL записывает вместо недопустимых; проверка значений его допускает.
- Столбец "updated_at" таблицы orders получает текущее время при каждом обновлении; в SQL Server это делает триггер.
Требует проверки
- В "signed_up" таблицы customers 1 значение - нулевая или невозможная дата, например 0000‑00‑00; SQL Server не может их хранить, поэтому записан NULL. Если эти даты что-то значат, замените их в источнике настоящими до создания дампа.
- В "shipped_at" таблицы orders 1 значение - нулевая или невозможная дата, например 0000‑00‑00 00:00:00; SQL Server не может их хранить, поэтому записан NULL. Если эти даты что-то значат, замените их в источнике настоящими до создания дампа.
Файл конвертируется на этом компьютере и никуда не загружается.
Другие примеры:
Что меняется при переходе с MariaDB на SQL Server
Каждая строка - это правило, которое применяет конвертер, и строка отчета, которую он пишет, когда правило что-то меняет в ваших данных.
TINYINT(1), BOOL
bit, если каждое значение 0 или 1, иначе smallint
BOOL в MySQL - это TINYINT(1), который может хранить любое число от -128 до 127. Столбец только с 0 и 1 становится bit; столбец с 2 или -1 остается числом, чтобы ни одно значение не изменило смысл.
Строка отчета: bool_kept_numeric
UNSIGNED integers
TINYINT UNSIGNED как tinyint; остальные как следующий более широкий целый тип с CHECK на неотрицательность, BIGINT UNSIGNED как bigint, если все значения помещаются, иначе decimal(38,0)
В SQL Server нет беззнаковых целых, кроме tinyint с диапазоном от 0 до 255. Более широкий тип вмещает весь беззнаковый диапазон, а проверка не пропускает отрицательные значения, как в MySQL.
Строка отчета: unsigned_widened
ZEROFILL and display widths
удаляется
Дополнение нулями - это способ показа числа, а не его часть. Числа сохраняются; если дополнение важно, форматируйте их при чтении.
Строка отчета: zerofill_dropped
FLOAT(M,D)
real или float, без масштаба
У чисел с плавающей точкой в SQL Server нет фиксированного масштаба. Записанные значения копируются как есть.
Строка отчета: float_scale_dropped
DECIMAL(p,s)
decimal(p,s) до 38 цифр; дальше nvarchar
decimal в SQL Server вмещает 38 цифр. Более широкие десятичные числа хранятся как текст, чтобы каждая цифра осталась точной.
Строка отчета: decimal_as_text
BIT(1), BIT(n)
bit; bigint до 63 бит; decimal(20,0) для BIT(64)
Один бит - это да или нет; более широкие битовые поля хранятся как число, которое составляют их биты.
zero, partial or impossible dates (0000-00-00, 2024-02-30)
NULL
SQL Server хранит только настоящие календарные даты. MySQL сохраняет нулевые и невозможные даты, если это позволяет режим SQL; они становятся NULL, а отчет их подсчитывает.
Строка отчета: invalid_date_null
NOT NULL columns with values that become NULL
NOT NULL снимается
Столбец, значения которого пришлось заменить на NULL, не может сохранить NOT NULL, иначе загрузка остановится.
Строка отчета: not_null_relaxed
DEFAULT '0000-00-00'
без значения по умолчанию
Значение по умолчанию, которое SQL Server не может хранить, опускается, а не заменяется выдуманной датой.
Строка отчета: zero_date_default
TIME
time, если каждое значение укладывается в сутки, иначе nvarchar
TIME в MySQL - это длительность от -838:59:59 до 838:59:59; time в SQL Server - это время суток. Столбец с более длинными или отрицательными значениями хранит их как текст.
Строка отчета: time_as_interval
YEAR
smallint с CHECK диапазона
В SQL Server нет типа для года; проверка допускает те же значения, что и MySQL.
CHAR(n), VARCHAR(n)
nvarchar(n)
nvarchar вмещает любой символ во всех поддерживаемых версиях, а MySQL возвращает значения CHAR без пробелов в конце, и nvarchar хранит их так же.
text with characters past U+FFFF (emoji) in VARCHAR(n)
nvarchar(2n) или nvarchar(max) свыше 4000
nvarchar считает единицы UTF-16, а эмодзи занимает две, поэтому столбец получает место для каждого значения.
Строка отчета: text_length_widened
DATETIME
datetime2
DATETIME - это показание часов без часового пояса, как datetime2.
TIMESTAMP
datetimeoffset в часовом поясе, указанном в дампе, или UTC, если он не указан
TIMESTAMP - это момент времени. Дампы указывают пояс, в котором он записан (mysqldump пишет UTC); без этого значения читаются как UTC, и отчет это отмечает.
Строка отчета: timestamp_zone_assumed
ENUM
nvarchar с CHECK значений
Текст с проверкой хранит те же значения.
ENUM holding '' (MySQL's error value)
пустое значение, которое допускает проверка
MySQL записывает пустую строку, когда недопустимое значение попадает в ENUM в нестрогом режиме SQL. Такие строки сохраняются, и проверка их допускает.
Строка отчета: enum_invalid_value
ENUM holding values outside its list
без CHECK
Значения, которых нет в списке, не прошли бы проверку, поэтому она не создается.
Строка отчета: enum_check_skipped
SET
nvarchar в записи MySQL ('a,b')
В SQL Server нет массивов; текст тот же, что возвращает MySQL.
JSON
nvarchar(max)
Функции JSON в SQL Server читают JSON из текста. Проверка ISJSON до SQL Server 2022 отклонила бы скалярные значения вроде 1 или "x", которые MySQL хранит.
NUL bytes in text
сохраняется
nvarchar может содержать символ NUL, поэтому значение копируется как есть.
text that isn't valid in its character set
неверные байты заменяются символом замены
Текст нужно прочитать как символы, чтобы записать его как nvarchar.
Строка отчета: invalid_utf8_replaced
text decoded twice (ñ)
копируется как есть
Дамп содержит именно эти символы, поэтому они копируются; отчет на них указывает.
Строка отчета: mojibake_suspected
AUTO_INCREMENT
IDENTITY, счетчик выставлен после скопированных id
Скопированные id загружаются с IDENTITY_INSERT, а счетчик продолжается после наибольшего из них или после AUTO_INCREMENT дампа, смотря что больше.
MyISAM AUTO_INCREMENT on the second column of a key
один счетчик на таблицу
MyISAM считает отдельно для каждой группы первого столбца ключа; в SQL Server один счетчик на таблицу.
Строка отчета: myisam_group_autoincrement
ON UPDATE CURRENT_TIMESTAMP
триггер AFTER UPDATE
Триггер записывает в столбец текущее время, когда обновление его не задает. Он соединяет строки по первичному ключу, поэтому у таблицы он должен быть.
Строка отчета: on_update_trigger
ON UPDATE CURRENT_TIMESTAMP on a table without a primary key
не переносится
Триггер находит обновленные строки по первичному ключу; без него это невозможно.
Строка отчета: on_update_without_key
generated columns
вычисляемые столбцы, PERSISTED, если источник их хранит
SQL Server вычисляет их теми же двумя способами.
generated columns with functions SQL Server lacks
обычный столбец
Формула, которую нельзя записать для SQL Server, оставляет обычный столбец и строку в отчете.
Строка отчета: generated_not_translated
INVISIBLE columns
обычные столбцы
В SQL Server нет невидимых столбцов.
Строка отчета: invisible_column
CHECK constraints
переводится, внутри CREATE TABLE
Встроенные проверки выполняются при загрузке каждой строки.
CHECK constraints with functions SQL Server lacks
не создается
Проверка, которую нельзя записать для SQL Server, опускается и попадает в отчет.
Строка отчета: check_skipped
CHECK ... NOT ENFORCED
не создается
MySQL хранит эти проверки, но не применяет их, поэтому строки могут их нарушать.
Строка отчета: check_not_enforced
defaults with functions SQL Server lacks
без значения по умолчанию
Значение по умолчанию, которое нельзя записать для SQL Server, опускается и попадает в отчет.
Строка отчета: default_not_translated
keys and indexes on a prefix, c(20)
индекс по всему столбцу
SQL Server индексирует столбцы целиком; ключ, уникальный по префиксу, уникален и по всему столбцу, поэтому загружается каждая строка.
Строка отчета: prefix_whole_column
FULLTEXT indexes
не создается
Полнотекстовому поиску в SQL Server нужен каталог и свои запросы.
Строка отчета: fulltext_not_created
SPATIAL indexes
не создается
Пространственному индексу по столбцу geometry нужен ограничивающий прямоугольник, которого нет в дампе.
Строка отчета: spatial_index_not_created
functional indexes, and indexes on columns of unlimited length
не создается
SQL Server не индексирует ни выражения, ни столбцы nvarchar(max) и varbinary(max).
Строка отчета: index_skipped
foreign keys
после данных WITH NOCHECK, затем проверка с предупреждением о строках без родителя
Дампы загружаются с FOREIGN_KEY_CHECKS=0, а MyISAM ничего не проверяет, поэтому строки без родительской записи встречаются часто. Ключ создается первым и проверяется последним; при строках без родителя он остается непроверенным с предупреждением, и загрузка не останавливается.
ON DELETE or ON UPDATE that cascades in a cycle or along a second path
NO ACTION
SQL Server не допускает каскады, которые могут дойти до таблицы дважды; MySQL их допускает.
Строка отчета: foreign_key_action_dropped
foreign keys to columns without a unique key
не создается
SQL Server требует первичный ключ или уникальный индекс без NULL на столбцах, на которые ссылается внешний ключ; InnoDB - нет.
Строка отчета: foreign_key_skipped
table and column names
как в источнике; переименовываются, если отличаются только регистром
Имена в SQL Server не учитывают регистр при обычной сортировке.
Строка отчета: identifier_renamed
names over 116 characters
сокращается
Имена в SQL Server вмещают 128 символов, часть из них уходит на числа, которые различают имена.
Строка отчета: name_shortened
GEOMETRY, POINT, POLYGON...
geometry, с SRID каждого значения
Собственный тип geometry в SQL Server сохраняет каждую фигуру и ее пространственную систему координат.
INET4, INET6, UUID (MariaDB)
nvarchar(39), uniqueidentifier
uniqueidentifier - это UUID в SQL Server; адреса хранятся как текст.
BINARY, VARBINARY, BLOB
binary, varbinary, varbinary(max)
Байты остаются байтами.
PARTITION BY
одна таблица
Строки те же; при необходимости секционируйте таблицу заново в SQL Server.
Строка отчета: partitions_dropped
WITH SYSTEM VERSIONING (MariaDB)
таблица с текущими строками
Дамп содержит только текущие строки.
Строка отчета: system_versioning_dropped
MyISAM, MEMORY and other engines
обычная таблица
В SQL Server один движок таблиц.
Строка отчета: engine_dropped
views, triggers, procedures, functions and events
перечисляются в отчете
Их код написан на языке MySQL, поэтому они перечислены, чтобы вы создали их заново.
Строка отчета: not_converted_objects
dumps without CREATE TABLE
типы определяются по значениям
Дамп, созданный с --no-create-info, содержит только строки, поэтому типы берутся из значений.
Строка отчета: no_schema
geometries in a dump without CREATE TABLE
geometry
Формат геометрии MySQL распознается по значениям.
_ci collations
сортировка базы данных, обычно без учета регистра
SQL Server при обычной сортировке сравнивает текст без учета регистра, как _ci в MySQL.
SET NAMES utf8 from utf8mb4 tables
конвертируется с предупреждением
mysqldump из MySQL 5.x по умолчанию пишет 3-байтовую utf8 и заменяет каждый эмодзи вопросительным знаком еще до того, как файл увидит какой-либо конвертер.
Строка отчета: dump_lost_four_byte_chars
dumps without SET NAMES whose text isn't UTF-8
читается как Latin-1 (Windows-1252)
latin1 в MySQL - это Windows-1252, обычная кодировка таких дампов.
Строка отчета: charset_guessed
sjis, cp932, gbk, big5 dumps
читается как UTF-8, с предупреждением
Эти кодировки пока не декодируются.
Строка отчета: unsupported_charset
UNHEX('..'), CONVERT(b'..', UNSIGNED), CONVERT(".." USING x), ST_GeomFromText('..') in rows
вычисляются
Некоторые программы дампа записывают значения как такие вызовы; они читаются как значения, которые возвращают, а в географическом WKT долгота ставится первой.
other expressions in rows
NULL
Конвертер, который не запускает базу данных, не может их вычислить.
Строка отчета: expression_value
DEFAULT in VALUES
значение столбца по умолчанию
Литеральное значение по умолчанию копируется в строку.
Строка отчета: default_keyword_filled
DEFAULT in VALUES without a literal default
NULL
Копировать нечего.
Строка отчета: default_keyword_null
REPLACE and INSERT IGNORE
обычные строки
В дампе одна строка на ключ, поэтому строки те же.
Строка отчета: replace_as_insert
types IntoSQL doesn't know
nvarchar(max)
Тип text вмещает любое значение; измените тип после загрузки.
Строка отчета: unknown_type
values that don't fit their column
NULL
Поврежденный или написанный вручную дамп может содержать значения, которые столбец не вмещает; они становятся NULL, чтобы остальное загрузилось.
Строка отчета: invalid_value_null
unreadable geometries
NULL
Байты, которые не являются геометрией, нельзя сохранить как геометрию.
Строка отчета: bad_geometry
CREATE SEQUENCE (MariaDB)
CREATE SEQUENCE ... AS bigint со следующим значением
В SQL Server есть последовательности с теми же параметрами; каждая продолжается с того места, где ее оставил дамп.
VECTOR(n) (MariaDB 11.7+)
nvarchar(max) с числами float в виде массива JSON
Векторный тип есть только в SQL Server 2025; массив JSON сохраняет каждое число float в любой версии.
Строка отчета: type_replaced
| В MariaDB | В SQL Server | Строка отчета |
|---|---|---|
| TINYINT(1), BOOL | bit, если каждое значение 0 или 1, иначе smallintBOOL в MySQL - это TINYINT(1), который может хранить любое число от -128 до 127. Столбец только с 0 и 1 становится bit; столбец с 2 или -1 остается числом, чтобы ни одно значение не изменило смысл. | bool_kept_numeric |
| UNSIGNED integers | TINYINT UNSIGNED как tinyint; остальные как следующий более широкий целый тип с CHECK на неотрицательность, BIGINT UNSIGNED как bigint, если все значения помещаются, иначе decimal(38,0)В SQL Server нет беззнаковых целых, кроме tinyint с диапазоном от 0 до 255. Более широкий тип вмещает весь беззнаковый диапазон, а проверка не пропускает отрицательные значения, как в MySQL. | unsigned_widened |
| ZEROFILL and display widths | удаляетсяДополнение нулями - это способ показа числа, а не его часть. Числа сохраняются; если дополнение важно, форматируйте их при чтении. | zerofill_dropped |
| FLOAT(M,D) | real или float, без масштабаУ чисел с плавающей точкой в SQL Server нет фиксированного масштаба. Записанные значения копируются как есть. | float_scale_dropped |
| DECIMAL(p,s) | decimal(p,s) до 38 цифр; дальше nvarchardecimal в SQL Server вмещает 38 цифр. Более широкие десятичные числа хранятся как текст, чтобы каждая цифра осталась точной. | decimal_as_text |
| BIT(1), BIT(n) | bit; bigint до 63 бит; decimal(20,0) для BIT(64)Один бит - это да или нет; более широкие битовые поля хранятся как число, которое составляют их биты. | |
| zero, partial or impossible dates (0000-00-00, 2024-02-30) | NULLSQL Server хранит только настоящие календарные даты. MySQL сохраняет нулевые и невозможные даты, если это позволяет режим SQL; они становятся NULL, а отчет их подсчитывает. | invalid_date_null |
| NOT NULL columns with values that become NULL | NOT NULL снимаетсяСтолбец, значения которого пришлось заменить на NULL, не может сохранить NOT NULL, иначе загрузка остановится. | not_null_relaxed |
| DEFAULT '0000-00-00' | без значения по умолчаниюЗначение по умолчанию, которое SQL Server не может хранить, опускается, а не заменяется выдуманной датой. | zero_date_default |
| TIME | time, если каждое значение укладывается в сутки, иначе nvarcharTIME в MySQL - это длительность от -838:59:59 до 838:59:59; time в SQL Server - это время суток. Столбец с более длинными или отрицательными значениями хранит их как текст. | time_as_interval |
| YEAR | smallint с CHECK диапазонаВ SQL Server нет типа для года; проверка допускает те же значения, что и MySQL. | |
| CHAR(n), VARCHAR(n) | nvarchar(n)nvarchar вмещает любой символ во всех поддерживаемых версиях, а MySQL возвращает значения CHAR без пробелов в конце, и nvarchar хранит их так же. | |
| text with characters past U+FFFF (emoji) in VARCHAR(n) | nvarchar(2n) или nvarchar(max) свыше 4000nvarchar считает единицы UTF-16, а эмодзи занимает две, поэтому столбец получает место для каждого значения. | text_length_widened |
| DATETIME | datetime2DATETIME - это показание часов без часового пояса, как datetime2. | |
| TIMESTAMP | datetimeoffset в часовом поясе, указанном в дампе, или UTC, если он не указанTIMESTAMP - это момент времени. Дампы указывают пояс, в котором он записан (mysqldump пишет UTC); без этого значения читаются как UTC, и отчет это отмечает. | timestamp_zone_assumed |
| ENUM | nvarchar с CHECK значенийТекст с проверкой хранит те же значения. | |
| ENUM holding '' (MySQL's error value) | пустое значение, которое допускает проверкаMySQL записывает пустую строку, когда недопустимое значение попадает в ENUM в нестрогом режиме SQL. Такие строки сохраняются, и проверка их допускает. | enum_invalid_value |
| ENUM holding values outside its list | без CHECKЗначения, которых нет в списке, не прошли бы проверку, поэтому она не создается. | enum_check_skipped |
| SET | nvarchar в записи MySQL ('a,b')В SQL Server нет массивов; текст тот же, что возвращает MySQL. | |
| JSON | nvarchar(max)Функции JSON в SQL Server читают JSON из текста. Проверка ISJSON до SQL Server 2022 отклонила бы скалярные значения вроде 1 или "x", которые MySQL хранит. | |
| NUL bytes in text | сохраняетсяnvarchar может содержать символ NUL, поэтому значение копируется как есть. | |
| text that isn't valid in its character set | неверные байты заменяются символом заменыТекст нужно прочитать как символы, чтобы записать его как nvarchar. | invalid_utf8_replaced |
| text decoded twice (ñ) | копируется как естьДамп содержит именно эти символы, поэтому они копируются; отчет на них указывает. | mojibake_suspected |
| AUTO_INCREMENT | IDENTITY, счетчик выставлен после скопированных idСкопированные id загружаются с IDENTITY_INSERT, а счетчик продолжается после наибольшего из них или после AUTO_INCREMENT дампа, смотря что больше. | |
| MyISAM AUTO_INCREMENT on the second column of a key | один счетчик на таблицуMyISAM считает отдельно для каждой группы первого столбца ключа; в SQL Server один счетчик на таблицу. | myisam_group_autoincrement |
| ON UPDATE CURRENT_TIMESTAMP | триггер AFTER UPDATEТриггер записывает в столбец текущее время, когда обновление его не задает. Он соединяет строки по первичному ключу, поэтому у таблицы он должен быть. | on_update_trigger |
| ON UPDATE CURRENT_TIMESTAMP on a table without a primary key | не переноситсяТриггер находит обновленные строки по первичному ключу; без него это невозможно. | on_update_without_key |
| generated columns | вычисляемые столбцы, PERSISTED, если источник их хранитSQL Server вычисляет их теми же двумя способами. | |
| generated columns with functions SQL Server lacks | обычный столбецФормула, которую нельзя записать для SQL Server, оставляет обычный столбец и строку в отчете. | generated_not_translated |
| INVISIBLE columns | обычные столбцыВ SQL Server нет невидимых столбцов. | invisible_column |
| CHECK constraints | переводится, внутри CREATE TABLEВстроенные проверки выполняются при загрузке каждой строки. | |
| CHECK constraints with functions SQL Server lacks | не создаетсяПроверка, которую нельзя записать для SQL Server, опускается и попадает в отчет. | check_skipped |
| CHECK ... NOT ENFORCED | не создаетсяMySQL хранит эти проверки, но не применяет их, поэтому строки могут их нарушать. | check_not_enforced |
| defaults with functions SQL Server lacks | без значения по умолчаниюЗначение по умолчанию, которое нельзя записать для SQL Server, опускается и попадает в отчет. | default_not_translated |
| keys and indexes on a prefix, c(20) | индекс по всему столбцуSQL Server индексирует столбцы целиком; ключ, уникальный по префиксу, уникален и по всему столбцу, поэтому загружается каждая строка. | prefix_whole_column |
| FULLTEXT indexes | не создаетсяПолнотекстовому поиску в SQL Server нужен каталог и свои запросы. | fulltext_not_created |
| SPATIAL indexes | не создаетсяПространственному индексу по столбцу geometry нужен ограничивающий прямоугольник, которого нет в дампе. | spatial_index_not_created |
| functional indexes, and indexes on columns of unlimited length | не создаетсяSQL Server не индексирует ни выражения, ни столбцы nvarchar(max) и varbinary(max). | index_skipped |
| foreign keys | после данных WITH NOCHECK, затем проверка с предупреждением о строках без родителяДампы загружаются с FOREIGN_KEY_CHECKS=0, а MyISAM ничего не проверяет, поэтому строки без родительской записи встречаются часто. Ключ создается первым и проверяется последним; при строках без родителя он остается непроверенным с предупреждением, и загрузка не останавливается. | |
| ON DELETE or ON UPDATE that cascades in a cycle or along a second path | NO ACTIONSQL Server не допускает каскады, которые могут дойти до таблицы дважды; MySQL их допускает. | foreign_key_action_dropped |
| foreign keys to columns without a unique key | не создаетсяSQL Server требует первичный ключ или уникальный индекс без NULL на столбцах, на которые ссылается внешний ключ; InnoDB - нет. | foreign_key_skipped |
| table and column names | как в источнике; переименовываются, если отличаются только регистромИмена в SQL Server не учитывают регистр при обычной сортировке. | identifier_renamed |
| names over 116 characters | сокращаетсяИмена в SQL Server вмещают 128 символов, часть из них уходит на числа, которые различают имена. | name_shortened |
| GEOMETRY, POINT, POLYGON... | geometry, с SRID каждого значенияСобственный тип geometry в SQL Server сохраняет каждую фигуру и ее пространственную систему координат. | |
| INET4, INET6, UUID (MariaDB) | nvarchar(39), uniqueidentifieruniqueidentifier - это UUID в SQL Server; адреса хранятся как текст. | |
| BINARY, VARBINARY, BLOB | binary, varbinary, varbinary(max)Байты остаются байтами. | |
| PARTITION BY | одна таблицаСтроки те же; при необходимости секционируйте таблицу заново в SQL Server. | partitions_dropped |
| WITH SYSTEM VERSIONING (MariaDB) | таблица с текущими строкамиДамп содержит только текущие строки. | system_versioning_dropped |
| MyISAM, MEMORY and other engines | обычная таблицаВ SQL Server один движок таблиц. | engine_dropped |
| views, triggers, procedures, functions and events | перечисляются в отчетеИх код написан на языке MySQL, поэтому они перечислены, чтобы вы создали их заново. | not_converted_objects |
| dumps without CREATE TABLE | типы определяются по значениямДамп, созданный с --no-create-info, содержит только строки, поэтому типы берутся из значений. | no_schema |
| geometries in a dump without CREATE TABLE | geometryФормат геометрии MySQL распознается по значениям. | |
| _ci collations | сортировка базы данных, обычно без учета регистраSQL Server при обычной сортировке сравнивает текст без учета регистра, как _ci в MySQL. | |
| SET NAMES utf8 from utf8mb4 tables | конвертируется с предупреждениемmysqldump из MySQL 5.x по умолчанию пишет 3-байтовую utf8 и заменяет каждый эмодзи вопросительным знаком еще до того, как файл увидит какой-либо конвертер. | dump_lost_four_byte_chars |
| dumps without SET NAMES whose text isn't UTF-8 | читается как Latin-1 (Windows-1252)latin1 в MySQL - это Windows-1252, обычная кодировка таких дампов. | charset_guessed |
| sjis, cp932, gbk, big5 dumps | читается как UTF-8, с предупреждениемЭти кодировки пока не декодируются. | unsupported_charset |
| UNHEX('..'), CONVERT(b'..', UNSIGNED), CONVERT(".." USING x), ST_GeomFromText('..') in rows | вычисляютсяНекоторые программы дампа записывают значения как такие вызовы; они читаются как значения, которые возвращают, а в географическом WKT долгота ставится первой. | |
| other expressions in rows | NULLКонвертер, который не запускает базу данных, не может их вычислить. | expression_value |
| DEFAULT in VALUES | значение столбца по умолчаниюЛитеральное значение по умолчанию копируется в строку. | default_keyword_filled |
| DEFAULT in VALUES without a literal default | NULLКопировать нечего. | default_keyword_null |
| REPLACE and INSERT IGNORE | обычные строкиВ дампе одна строка на ключ, поэтому строки те же. | replace_as_insert |
| types IntoSQL doesn't know | nvarchar(max)Тип text вмещает любое значение; измените тип после загрузки. | unknown_type |
| values that don't fit their column | NULLПоврежденный или написанный вручную дамп может содержать значения, которые столбец не вмещает; они становятся NULL, чтобы остальное загрузилось. | invalid_value_null |
| unreadable geometries | NULLБайты, которые не являются геометрией, нельзя сохранить как геометрию. | bad_geometry |
| CREATE SEQUENCE (MariaDB) | CREATE SEQUENCE ... AS bigint со следующим значениемВ SQL Server есть последовательности с теми же параметрами; каждая продолжается с того места, где ее оставил дамп. | |
| VECTOR(n) (MariaDB 11.7+) | nvarchar(max) с числами float в виде массива JSONВекторный тип есть только в SQL Server 2025; массив JSON сохраняет каждое число float в любой версии. | type_replaced |
Загрузите скрипт в SQL Server
Скрипт создает таблицы, копирует строки, затем добавляет ключи, индексы и внешние ключи, поэтому загрузка идет быстро и останавливается на первой ошибке.
sqlcmd -b -f 65001 -S localhost -d mydb -i mariadb.sql_server.sqlВнешние ключи добавляются WITH NOCHECK, а затем проверяются. Если строка ссылается на несуществующую строку, скрипт сообщает, какое это ограничение, и оставляет его непроверенным, а не прерывается на полпути.
Для большого дампа запускайте sqlcmd на той же машине, где работает сервер. Каждый пакет до 1000 строк фиксируется отдельно, поэтому журнал транзакций остается небольшим.
Как создать дамп MariaDB для лучшего результата
Конвертер читает то, что есть в дампе. Эти параметры сохраняют в нем больше ваших данных:
- --default-character-set=utf8mb4 сохраняет эмодзи и другие 4-байтовые символы, которые дамп в utf8mb3 теряет еще до конвертера.
- --hex-blob записывает двоичные столбцы и значения VECTOR в шестнадцатеричном виде, который не портится при копировании между системами.
- --routines --triggers --events добавляют эти объекты в дамп, чтобы отчет мог их перечислить.
Что не конвертируется
Представления, триггеры, хранимые процедуры, функции и события написаны на собственном языке MariaDB. Они перечислены в отчете по имени и никогда не удаляются молча, чтобы вы могли переписать их для SQL Server.
Вопросы о MariaDB в SQL Server
Нет ответа на ваш вопрос? Напишите нам через страницу контактов, и вам ответит человек. Страница контактов
Мой дамп загружается на сервер?
Нет. Конвертер работает в вашем браузере и читает дамп с диска по частям, поэтому он никогда не покидает ваш компьютер. Приложение для компьютера и командная строка тоже конвертируют на вашем компьютере.
Насколько большим может быть дамп?
Конвертер никогда не держит весь дамп в памяти: он читает файл дважды, по диапазонам, и пишет скрипт по ходу чтения. Дампы в несколько гигабайт конвертируются в браузере, в приложении для компьютера и в командной строке.
Из каких версий MariaDB может быть дамп?
Дампы из mariadb-dump и mysqldump на MariaDB с 10.3 по 12, с одним INSERT на таблицу или одним на строку. Каждый тестовый дамп создан в MariaDB 10.11, 11.4 и 11.8 и сверен с источником ячейка за ячейкой.
Сохраняются ли столбцы UUID, INET6, JSON и VECTOR?
UUID становится uniqueidentifier, столбцы INET - nvarchar, JSON - nvarchar(max), а VECTOR - массивом JSON из его чисел float. Нулевые даты становятся NULL, и отчет их подсчитывает.
Сохраняются ли значения AUTO_INCREMENT и последовательности?
Да. Каждый столбец AUTO_INCREMENT становится столбцом IDENTITY, который продолжается после наибольшего id. Последовательности становятся последовательностями SQL Server, а значения по умолчанию, которые берутся из них, продолжают из них браться.
А хранимые процедуры и триггеры?
Они перечислены в отчете по имени и не конвертируются, потому что каждая база данных пишет их на своем языке.
На каких версиях SQL Server загружается скрипт?
SQL Server с 2017 по 2025. Один и тот же скрипт загружается на каждой из них и останавливается на первой ошибке, если что-то пойдет не так.