Конвертация Oracle в SQL Server
Перетащите файл .sql, который записывает Database Export в SQL Developer или SQLcl, с таблицами и командами Insert, и скачайте скрипт SQL Server с теми же таблицами, ключами, индексами и данными. Каждое значение, которое SQL Server не может хранить как есть, и каждый объект, который он не переносит, указаны в отчете.
18 строк конвертировано, 2 исправления, ни одна не отклонена
Таблицы в shop_2024_oracle.sqlДамп Oracle · создан программой SQL Developer · utf-8
customers8 строк1
7 столбцов id bigint not null name nvarchar(200) not null email nvarchar(150) not null country nvarchar(2) not null is_active smallint not null signed_up datetime2(0) created_at datetime2(0) not null orders10 строк1
9 столбцов id bigint not null customer_id bigint not null invoice bigint status nvarchar(10) 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)
-- Written by IntoSQL from a Oracle 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 1020 INCREMENT BY 1 MINVALUE 1;
GO
CREATE TABLE [dbo].[customers] (
[id] bigint IDENTITY(1, 1) NOT NULL,
[name] nvarchar(200) COLLATE Latin1_General_100_BIN2 NOT NULL,
[email] nvarchar(150) COLLATE Latin1_General_100_BIN2 NOT NULL,
[country] nvarchar(2) COLLATE Latin1_General_100_BIN2 DEFAULT N'US' NOT NULL,
[is_active] smallint DEFAULT 1 NOT NULL,
[signed_up] datetime2(0) NULL,
[created_at] datetime2(0) DEFAULT SYSDATETIME() NOT NULL,
CONSTRAINT [check1] CHECK ([is_active] IN (0, 1)),
CONSTRAINT [PK_customers] PRIMARY KEY ([id])
);
GO
CREATE TABLE [dbo].[orders] (
[id] bigint IDENTITY(1, 1) NOT NULL,
[customer_id] bigint NOT NULL,
[invoice] bigint DEFAULT (NEXT VALUE FOR [dbo].[invoice_numbers]) NULL,
[status] nvarchar(10) COLLATE Latin1_General_100_BIN2 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) COLLATE Latin1_General_100_BIN2 NULL,
CONSTRAINT [check1_2] CHECK ([status] IN (N'pending', N'paid', N'shipped', N'cancelled')),
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 00:00:00','2023-01-15 10:24:00.0000000');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [signed_up], [created_at]) VALUES
(2,N'Zoë Müller',N'zoe@example.de',N'DE',1,'2023-02-03 00:00:00','2023-02-03 08:11:42.0000000');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [signed_up], [created_at]) VALUES
(3,N'José Peña',N'jose@example.es',N'ES',0,'2023-03-21 00:00:00','2023-03-21 19:05:17.0000000');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [signed_up], [created_at]) VALUES
(4,N'李雷',N'lilei@example.cn',N'CN',1,'2023-05-09 00:00:00','2023-05-09 02:40:00.0000000');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [signed_up], [created_at]) VALUES
(5,N'Noah O''Brien',N'noah@example.ie',N'IE',1,NULL,'2023-06-30 14:00:00.0000000');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [signed_up], [created_at]) VALUES
(6,N'Amélie Laurent',N'amelie@example.fr',N'FR',1,'2024-01-02 00:00:00','2024-01-02 09:30:00.0000000');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [signed_up], [created_at]) VALUES
(7,N'Ravi Patel',N'ravi@example.in',N'IN',0,'2024-02-29 00:00:00','2024-02-29 23:59:59.0000000');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [signed_up], [created_at]) VALUES
(8,N'Sofia Rossi 🌻',N'sofia@example.it',N'IT',1,'2024-04-12 00:00:00','2024-04-12 12:12:12.0000000');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(1,1,1000,N'shipped',129.9,3,'2024-03-01 10:00:00','2024-03-02 16:30:00',NULL);
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(2,2,1001,N'paid',54,1,'2024-03-02 11:15:00',NULL,N'Gift wrap 🎁');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(3,1,1002,N'cancelled',12.5,1,'2024-03-03 09:45:00',NULL,N'Customer changed their mind');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(4,4,1003,N'shipped',980,12,'2024-03-05 02:10:00','2024-03-07 08:00:00',N'请小心轻放');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(5,5,1004,N'pending',45.75,2,'2024-03-08 17:20:00',NULL,N'Leave at the door; ring twice');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(6,6,1005,N'shipped',310.4,5,'2024-03-10 13:00:00','2024-03-11 09:00:00',N'Fragile: "glass"');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(7,8,1006,N'paid',76.2,2,'2024-03-11 18:45:00',NULL,NULL);
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(8,2,1007,N'paid',19.99,1,'2024-03-12 08:00:00',NULL,N'Paid at the counter');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(9,3,1008,N'shipped',64,2,'2024-03-14 15:30:00',NULL,N'Shipping date never recorded');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(10,7,1009,N'paid',1499,1,'2024-03-15 21:05:00',NULL,N'C:\Users\ravi\invoice.pdf');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
-- Indexes, foreign keys, counters and triggers, after the rows.
CREATE UNIQUE INDEX [customers_email_uk] ON [dbo].[customers] ([email]);
CREATE INDEX [orders_status_date_ix] ON [dbo].[orders] ([status], [ordered_at]);
ALTER TABLE [dbo].[orders] WITH NOCHECK ADD CONSTRAINT [orders_customer_fk] FOREIGN KEY ([customer_id]) REFERENCES [dbo].[customers] ([id]);
BEGIN TRY ALTER TABLE [dbo].[orders] WITH CHECK CHECK CONSTRAINT [orders_customer_fk]; END TRY BEGIN CATCH PRINT N'Foreign key ' + N'[orders_customer_fk]' + 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 < 0 SET @next = 0; 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 < 0 SET @next = 0; DBCC CHECKIDENT (N'[dbo].[orders]', RESEED, @next) WITH NO_INFOMSGS; END;
GO
GO
Исправления
- "name" таблицы customers содержит символы, которые SQL Server считает дважды, например эмодзи, поэтому тип nvarchar(200).
- "note" таблицы orders содержит символы, которые SQL Server считает дважды, например эмодзи, поэтому тип nvarchar(510).
Файл конвертируется на этом компьютере и никуда не загружается.
Другие примеры:
Что меняется при переходе с Oracle на SQL Server
Каждая строка - это правило, которое применяет конвертер, и строка отчета, которую он пишет, когда правило что-то меняет в ваших данных.
BOOLEAN (23ai)
bit
В SQL Server нет логического столбца, поэтому TRUE и FALSE становятся 1 и 0.
VARCHAR2(n BYTE|CHAR), NVARCHAR2(n), CHAR(n), NCHAR(n), CLOB, NCLOB, LONG
nvarchar(n), nchar(n) и nvarchar(max)
Длины считаются в символах, считал ли Oracle байты или символы, поэтому каждое значение помещается.
VARCHAR2 and NVARCHAR2 past what the target's own types hold
nvarchar(2n) или nvarchar(max) свыше 4000
nvarchar считает единицы UTF-16, а эмодзи занимает две, поэтому столбец получает место для каждого значения.
Строка отчета: text_length_widened
NUMBER, NUMBER(p,s), FLOAT(b)
decimal(p,s) или bigint
NUMBER сохраняет каждую цифру; NUMBER без точности, все значения которого - целые числа до 18 цифр, становится 64-битным целым, а отрицательный масштаб хранит столько же цифр до запятой.
INTERVAL YEAR TO MONTH, INTERVAL DAY TO SECOND
nvarchar(100) с текстом Oracle, например +01-06
В SQL Server нет типа interval; текст сохраняет каждую часть.
Строка отчета: type_replaced
DATE, TIMESTAMP(p)
datetime2(p)
DATE в Oracle хранит время с точностью до секунды, поэтому это дата и время. Экспорт в американском или немецком сеансе записывает даты без времени и века (DD-MON-RR); экспортируйте в сеансе ISO (SYYYY-MM-DD HH24:MI:SS), чтобы их сохранить.
TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH LOCAL TIME ZONE
datetimeoffset со смещением каждого значения
Тот же тип и те же значения.
JSON (21c), and CLOB holding JSON
nvarchar(max)
Те же значения JSON; SQL NULL, который экспорт записал как 'null', остается NULL.
BLOB, RAW(n), LONG RAW
binary(n), varbinary(n) и varbinary(max)
Байты остаются байтами.
ROWID, UROWID, XMLTYPE, SDO_GEOMETRY
nvarchar(max), а для XMLTYPE - xml
У собственных типов Oracle нет аналогов; их значения сохраняют свой текст, включая значения ROWID, хотя вне Oracle они ничего не значат.
collations that ignore case (BINARY_CI)
та же сортировка у каждого столбца
Столбцы сравниваются и сортируются как раньше, а уникальные ключи различают те же строки.
identity columns, and a sequence a BEFORE INSERT trigger assigns
IDENTITY, продолжается после наибольшего id
Скопированные id загружаются как есть, а счетчик продолжается после наибольшего. Столбец, который триггер заполняет из последовательности (способ до 12c), тоже становится столбцом identity.
identity columns the target can't count
обычное целое
SQL Server нумерует один столбец IDENTITY на таблицу; любой другой сохраняет свои значения без счетчика.
Строка отчета: counter_dropped
CREATE SEQUENCE
CREATE SEQUENCE с теми же параметрами
Экспорт записывает, до какого значения дошла последовательность, как ее START WITH, поэтому она продолжается оттуда.
virtual columns (GENERATED ALWAYS AS ... VIRTUAL)
вычисляемые столбцы
SQL Server вычисляет их по той же формуле; значения, которые экспорт для них записал, опускаются.
virtual columns with functions IntoSQL doesn't write, and the || operator
обычный столбец
Формула, которую нельзя записать для SQL Server, оставляет обычный столбец и строку в отчете; значения, которые экспорт записал для виртуальных столбцов, опускаются, и SQL Server не может их вычислить.
Строка отчета: generated_not_translated
defaults with functions IntoSQL doesn't write (SYS_GUID(), ||)
без значения по умолчанию
Значение по умолчанию, которое нельзя записать, опускается и попадает в отчет.
Строка отчета: default_not_translated
CHECK constraints
переводится
Те же проверки, применяемые при загрузке каждой строки.
CHECK constraints with functions IntoSQL doesn't write
не создается
Проверка, которую нельзя записать, опускается и попадает в отчет.
Строка отчета: check_skipped
CHECK constraints that are DISABLE or ENABLE NOVALIDATE
не создается
Oracle не применяет эти проверки к уже существующим строкам, поэтому строки могут их нарушать.
Строка отчета: check_not_enforced
function-based, bitmap and domain indexes
не создается
IntoSQL создает индексы b-tree по целым столбцам; остальные создайте заново после загрузки.
Строка отчета: index_skipped
foreign keys
после данных WITH NOCHECK, затем проверка с предупреждением о строках без родителя
Ключ создается после строк и проверяется последним; при строках без родителя он остается непроверенным с предупреждением, и загрузка не останавливается.
ON DELETE CASCADE that cascades in a cycle or along a second path
NO ACTION
SQL Server не допускает каскады, которые образуют цикл или идут вторым путем, поэтому ключ создается без этого действия, а отчет его называет.
Строка отчета: foreign_key_action_dropped
foreign keys to tables the export doesn't create, and DISABLE or NOVALIDATE ones
не создается
Ключ не может ссылаться на таблицу, которой нет, а у ключа, который Oracle не проверяет, могут быть строки без родителя.
Строка отчета: foreign_key_skipped
partitioned tables
одна таблица со строками всех секций
Строки те же; при необходимости секционируйте таблицу заново в SQL Server.
Строка отчета: partitions_dropped
NOT NULL columns with values that become NULL
NOT NULL снимается
Столбец, значения которого пришлось заменить на NULL, не может сохранить NOT NULL, иначе загрузка остановится.
Строка отчета: not_null_relaxed
views, synonyms, types, packages, procedures, functions and other triggers
перечисляются в отчете
Их код написан на PL/SQL, поэтому они перечислены, чтобы вы создали их заново.
Строка отчета: not_converted_objects
exports without CREATE TABLE (data only)
типы определяются по значениям
Экспорт только с данными содержит лишь строки, поэтому типы берутся из значений.
Строка отчета: no_schema
expressions in INSERT values other than the ones exports write
NULL
Конвертер, который не запускает базу данных, не может их вычислить; to_date, to_timestamp, TO_CLOB, HEXTORAW и другие функции, которые пишут экспорты, читаются.
Строка отчета: expression_value
types IntoSQL doesn't know, and object types
nvarchar(max)
Тип text вмещает любое значение; измените тип после загрузки.
Строка отчета: unknown_type
dates before year 1 and time zones given as region names
NULL
Значение, которое не является датой, становится NULL, и отчет его подсчитывает.
Строка отчета: date_out_of_range
NaN and Infinity in BINARY_FLOAT and BINARY_DOUBLE
NULL
Типы с плавающей точкой в SQL Server не поддерживают NaN и бесконечность, поэтому такие значения становятся NULL, а отчет их подсчитывает.
Строка отчета: invalid_value_null
NUL characters in text
сохраняется
nvarchar может содержать символ NUL, поэтому значение копируется как есть.
text that isn't valid in its encoding
неверные байты заменяются символом замены
Скрипт в UTF-8, и каждое значение должно быть корректным текстом.
Строка отчета: invalid_utf8_replaced
text decoded twice (ñ)
копируется как есть
Скрипт содержит именно эти символы, поэтому они копируются; отчет на них указывает.
Строка отчета: mojibake_suspected
| В Oracle | В SQL Server | Строка отчета |
|---|---|---|
| BOOLEAN (23ai) | bitВ SQL Server нет логического столбца, поэтому TRUE и FALSE становятся 1 и 0. | |
| VARCHAR2(n BYTE|CHAR), NVARCHAR2(n), CHAR(n), NCHAR(n), CLOB, NCLOB, LONG | nvarchar(n), nchar(n) и nvarchar(max)Длины считаются в символах, считал ли Oracle байты или символы, поэтому каждое значение помещается. | |
| VARCHAR2 and NVARCHAR2 past what the target's own types hold | nvarchar(2n) или nvarchar(max) свыше 4000nvarchar считает единицы UTF-16, а эмодзи занимает две, поэтому столбец получает место для каждого значения. | text_length_widened |
| NUMBER, NUMBER(p,s), FLOAT(b) | decimal(p,s) или bigintNUMBER сохраняет каждую цифру; NUMBER без точности, все значения которого - целые числа до 18 цифр, становится 64-битным целым, а отрицательный масштаб хранит столько же цифр до запятой. | |
| INTERVAL YEAR TO MONTH, INTERVAL DAY TO SECOND | nvarchar(100) с текстом Oracle, например +01-06В SQL Server нет типа interval; текст сохраняет каждую часть. | type_replaced |
| DATE, TIMESTAMP(p) | datetime2(p)DATE в Oracle хранит время с точностью до секунды, поэтому это дата и время. Экспорт в американском или немецком сеансе записывает даты без времени и века (DD-MON-RR); экспортируйте в сеансе ISO (SYYYY-MM-DD HH24:MI:SS), чтобы их сохранить. | |
| TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH LOCAL TIME ZONE | datetimeoffset со смещением каждого значенияТот же тип и те же значения. | |
| JSON (21c), and CLOB holding JSON | nvarchar(max)Те же значения JSON; SQL NULL, который экспорт записал как 'null', остается NULL. | |
| BLOB, RAW(n), LONG RAW | binary(n), varbinary(n) и varbinary(max)Байты остаются байтами. | |
| ROWID, UROWID, XMLTYPE, SDO_GEOMETRY | nvarchar(max), а для XMLTYPE - xmlУ собственных типов Oracle нет аналогов; их значения сохраняют свой текст, включая значения ROWID, хотя вне Oracle они ничего не значат. | |
| collations that ignore case (BINARY_CI) | та же сортировка у каждого столбцаСтолбцы сравниваются и сортируются как раньше, а уникальные ключи различают те же строки. | |
| identity columns, and a sequence a BEFORE INSERT trigger assigns | IDENTITY, продолжается после наибольшего idСкопированные id загружаются как есть, а счетчик продолжается после наибольшего. Столбец, который триггер заполняет из последовательности (способ до 12c), тоже становится столбцом identity. | |
| identity columns the target can't count | обычное целоеSQL Server нумерует один столбец IDENTITY на таблицу; любой другой сохраняет свои значения без счетчика. | counter_dropped |
| CREATE SEQUENCE | CREATE SEQUENCE с теми же параметрамиЭкспорт записывает, до какого значения дошла последовательность, как ее START WITH, поэтому она продолжается оттуда. | |
| virtual columns (GENERATED ALWAYS AS ... VIRTUAL) | вычисляемые столбцыSQL Server вычисляет их по той же формуле; значения, которые экспорт для них записал, опускаются. | |
| virtual columns with functions IntoSQL doesn't write, and the || operator | обычный столбецФормула, которую нельзя записать для SQL Server, оставляет обычный столбец и строку в отчете; значения, которые экспорт записал для виртуальных столбцов, опускаются, и SQL Server не может их вычислить. | generated_not_translated |
| defaults with functions IntoSQL doesn't write (SYS_GUID(), ||) | без значения по умолчаниюЗначение по умолчанию, которое нельзя записать, опускается и попадает в отчет. | default_not_translated |
| CHECK constraints | переводитсяТе же проверки, применяемые при загрузке каждой строки. | |
| CHECK constraints with functions IntoSQL doesn't write | не создаетсяПроверка, которую нельзя записать, опускается и попадает в отчет. | check_skipped |
| CHECK constraints that are DISABLE or ENABLE NOVALIDATE | не создаетсяOracle не применяет эти проверки к уже существующим строкам, поэтому строки могут их нарушать. | check_not_enforced |
| function-based, bitmap and domain indexes | не создаетсяIntoSQL создает индексы b-tree по целым столбцам; остальные создайте заново после загрузки. | index_skipped |
| foreign keys | после данных WITH NOCHECK, затем проверка с предупреждением о строках без родителяКлюч создается после строк и проверяется последним; при строках без родителя он остается непроверенным с предупреждением, и загрузка не останавливается. | |
| ON DELETE CASCADE that cascades in a cycle or along a second path | NO ACTIONSQL Server не допускает каскады, которые образуют цикл или идут вторым путем, поэтому ключ создается без этого действия, а отчет его называет. | foreign_key_action_dropped |
| foreign keys to tables the export doesn't create, and DISABLE or NOVALIDATE ones | не создаетсяКлюч не может ссылаться на таблицу, которой нет, а у ключа, который Oracle не проверяет, могут быть строки без родителя. | foreign_key_skipped |
| partitioned tables | одна таблица со строками всех секцийСтроки те же; при необходимости секционируйте таблицу заново в SQL Server. | partitions_dropped |
| NOT NULL columns with values that become NULL | NOT NULL снимаетсяСтолбец, значения которого пришлось заменить на NULL, не может сохранить NOT NULL, иначе загрузка остановится. | not_null_relaxed |
| views, synonyms, types, packages, procedures, functions and other triggers | перечисляются в отчетеИх код написан на PL/SQL, поэтому они перечислены, чтобы вы создали их заново. | not_converted_objects |
| exports without CREATE TABLE (data only) | типы определяются по значениямЭкспорт только с данными содержит лишь строки, поэтому типы берутся из значений. | no_schema |
| expressions in INSERT values other than the ones exports write | NULLКонвертер, который не запускает базу данных, не может их вычислить; to_date, to_timestamp, TO_CLOB, HEXTORAW и другие функции, которые пишут экспорты, читаются. | expression_value |
| types IntoSQL doesn't know, and object types | nvarchar(max)Тип text вмещает любое значение; измените тип после загрузки. | unknown_type |
| dates before year 1 and time zones given as region names | NULLЗначение, которое не является датой, становится NULL, и отчет его подсчитывает. | date_out_of_range |
| NaN and Infinity in BINARY_FLOAT and BINARY_DOUBLE | NULLТипы с плавающей точкой в SQL Server не поддерживают NaN и бесконечность, поэтому такие значения становятся NULL, а отчет их подсчитывает. | invalid_value_null |
| NUL characters in text | сохраняетсяnvarchar может содержать символ NUL, поэтому значение копируется как есть. | |
| text that isn't valid in its encoding | неверные байты заменяются символом заменыСкрипт в UTF-8, и каждое значение должно быть корректным текстом. | invalid_utf8_replaced |
| text decoded twice (ñ) | копируется как естьСкрипт содержит именно эти символы, поэтому они копируются; отчет на них указывает. | mojibake_suspected |
Загрузите скрипт в SQL Server
Скрипт создает таблицы, копирует строки, затем добавляет ключи, индексы и внешние ключи, поэтому загрузка идет быстро и останавливается на первой ошибке.
sqlcmd -b -f 65001 -S localhost -d mydb -i oracle.sql_server.sqlВнешние ключи добавляются WITH NOCHECK, а затем проверяются. Если строка ссылается на несуществующую строку, скрипт сообщает, какое это ограничение, и оставляет его непроверенным, а не прерывается на полпути.
Для большого дампа запускайте sqlcmd на той же машине, где работает сервер. Каждый пакет до 1000 строк фиксируется отдельно, поэтому журнал транзакций остается небольшим.
Как создать дамп Oracle для лучшего результата
Конвертер читает то, что есть в дампе. Эти параметры сохраняют в нем больше ваших данных:
- В SQL Developer выберите Tools, Database Export, с DDL и форматом данных Insert. SQLcl записывает то же самое с SET SQLFORMAT INSERT.
- Выполните ALTER SESSION SET NLS_DATE_FORMAT = 'SYYYY-MM-DD HH24:MI:SS' перед экспортом: формат по умолчанию записывает даты без времени и века.
- Файл .dmp из exp или expdp двоичный: импортируйте его в базу Oracle, например в Oracle Database Free в Docker, и экспортируйте через SQL Developer.
Что не конвертируется
Представления, пакеты, процедуры, функции, триггеры, типы и синонимы написаны на PL/SQL. Они перечислены в отчете по имени и никогда не удаляются молча, чтобы вы могли переписать их для SQL Server.
Вопросы о Oracle в SQL Server
Нет ответа на ваш вопрос? Напишите нам через страницу контактов, и вам ответит человек. Страница контактов
Мой дамп загружается на сервер?
Нет. Конвертер работает в вашем браузере и читает дамп с диска по частям, поэтому он никогда не покидает ваш компьютер. Приложение для компьютера и командная строка тоже конвертируют на вашем компьютере.
Насколько большим может быть дамп?
Конвертер никогда не держит весь дамп в памяти: он читает файл дважды, по диапазонам, и пишет скрипт по ходу чтения. Дампы в несколько гигабайт конвертируются в браузере, в приложении для компьютера и в командной строке.
Можно ли конвертировать файл .dmp из exp или expdp?
Не напрямую: Data Pump и исходный Export пишут двоичный формат, который читает только Oracle. Импортируйте его в любую базу Oracle (Oracle Database Free работает в Docker) и экспортируйте через Database Export в SQL Developer или SQLcl. Конвертер сообщает об этом, когда получает файл .dmp.
Из каких версий Oracle может быть экспорт?
Экспорты из SQL Developer и SQLcl с определениями таблиц из DBMS_METADATA, из Oracle 11g и новее. Каждый тестовый экспорт создан в Oracle 21c и 23ai, в американском, немецком и ISO-сеансах, и сверен с источником ячейка за ячейкой.
Что происходит с NUMBER, DATE и другими типами Oracle?
NUMBER становится decimal или bigint для целых чисел; DATE становится datetime2(0) и сохраняет время; текст - nvarchar с точным сравнением, как в Oracle; CLOB - nvarchar(max), BLOB - varbinary(max). NaN и Infinity становятся NULL, а отчет их подсчитывает.
Сохраняются ли столбцы identity и последовательности?
Да. Столбцы identity становятся столбцами IDENTITY и продолжаются после наибольшего id; последовательности становятся последовательностями SQL Server, а значения по умолчанию, которые берутся из них, продолжают из них браться.
А пакеты, процедуры и триггеры PL/SQL?
Они перечислены в отчете по имени и не конвертируются, потому что каждая база данных пишет их на своем языке.
На каких версиях SQL Server загружается скрипт?
SQL Server с 2017 по 2025. Один и тот же скрипт загружается на каждой из них и останавливается на первой ошибке, если что-то пойдет не так.