Перейти к содержимому
Главная страница IntoSQL

Конвертация SQL Server в Oracle

Перетащите скрипт, который Generate Scripts в SSMS записывает со схемой и данными, в формате .sql или .sql.gz, в UTF-16 или UTF-8, и скачайте скрипт Oracle с теми же таблицами, ключами, индексами и данными. Каждое значение, которое Oracle не может хранить как есть, и каждый объект, который он не переносит, указаны в отчете.

Ваш файл
sqlshop_2024_sqlserver.sqlПример файла, 11 кБ
Ваша база данных

18 строк конвертировано, 2 исправления, ни одна не отклонена

Показать

Таблицы в shop_2024_sqlserver.sqlДамп SQL Server · создан программой SQL Server Management Objects · utf-8

  • ordersзаписана как ORDERS10 строк1
    11 столбцов
    IDNUMBER(10) not null
    CUSTOMER_IDNUMBER(10) not null
    STATUSVARCHAR2(10 CHAR) not null
    TOTALNUMBER(19,4) not null
    ITEMSNUMBER(3) not null
    ORDERED_ATTIMESTAMP(0) not null
    SHIPPED_ATTIMESTAMP(7)
    NOTECLOB
    DETAILSCLOB
    ORDER_REFVARCHAR2(36 CHAR) not null
    TOTAL_WITH_TAXNUMBER(12,2)
  • customersзаписана как CUSTOMERS8 строк1
    8 столбцов
    IDNUMBER(10) not null
    NAMEVARCHAR2(100 CHAR) not null
    EMAILVARCHAR2(200 CHAR) not null
    COUNTRYVARCHAR2(2 CHAR) not null
    IS_ACTIVENUMBER(1) not null
    SIGNED_UPDATE
    CREATED_ATTIMESTAMP(0) WITH TIME ZONE not null
    ROW_VERSIONRAW(8)

Не конвертировано

  • Представление paid_orders
  • Триггер orders_no_negative

Каждая база данных пишет их на своем языке. Перепишите их для Oracle.

-- Written by IntoSQL from a SQL Server dump. Load it with: NLS_LANG=.AL32UTF8 sqlplus -S -L <user>/<password>@<database> @<file>
WHENEVER SQLERROR EXIT FAILURE ROLLBACK;
SET DEFINE OFF;
SET SQLBLANKLINES ON;
SET FEEDBACK OFF;
SET SERVEROUTPUT ON;
CREATE OR REPLACE FUNCTION "INTOSQL_CLOB" (p SYS.ODCIVARCHAR2LIST) RETURN CLOB IS
    r CLOB;
BEGIN
    DBMS_LOB.CREATETEMPORARY(r, TRUE);
    FOR i IN 1 .. p.COUNT LOOP
        IF p(i) IS NOT NULL THEN
            DBMS_LOB.WRITEAPPEND(r, LENGTH2(p(i)), p(i));
        END IF;
    END LOOP;
    RETURN r;
END;
/
CREATE OR REPLACE FUNCTION "INTOSQL_BLOB" (p SYS.ODCIVARCHAR2LIST) RETURN BLOB IS
    r BLOB;
    piece RAW(2000);
BEGIN
    DBMS_LOB.CREATETEMPORARY(r, TRUE);
    FOR i IN 1 .. p.COUNT LOOP
        piece := HEXTORAW(p(i));
        DBMS_LOB.WRITEAPPEND(r, UTL_RAW.LENGTH(piece), piece);
    END LOOP;
    RETURN r;
END;
/

CREATE TABLE "ORDERS" (
    "ID" NUMBER(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 1),
    "CUSTOMER_ID" NUMBER(10) NOT NULL,
    "STATUS" VARCHAR2(10 CHAR) DEFAULT 'pending' NOT NULL,
    "TOTAL" NUMBER(19,4) NOT NULL,
    "ITEMS" NUMBER(3) DEFAULT 1 NOT NULL,
    "ORDERED_AT" TIMESTAMP(0) NOT NULL,
    "SHIPPED_AT" TIMESTAMP(7),
    "NOTE" CLOB,
    "DETAILS" CLOB,
    "ORDER_REF" VARCHAR2(36 CHAR) NOT NULL,
    "TOTAL_WITH_TAX" NUMBER(12,2) GENERATED ALWAYS AS (CAST(CAST("TOTAL" * (1.16) AS NUMBER(12,2)) AS NUMBER(12,2))) VIRTUAL,
    CONSTRAINT "CK_ORDERS_ITEMS" CHECK ("ITEMS" >= 0),
    CONSTRAINT "CHECK2" CHECK ("STATUS" = 'cancelled' OR "STATUS" = 'shipped' OR "STATUS" = 'paid' OR "STATUS" = 'pending'),
    CONSTRAINT "CHECK3" CHECK ("TOTAL" >= (0))
);

CREATE TABLE "CUSTOMERS" (
    "ID" NUMBER(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 1),
    "NAME" VARCHAR2(100 CHAR) NOT NULL,
    "EMAIL" VARCHAR2(200 CHAR) NOT NULL,
    "COUNTRY" VARCHAR2(2 CHAR) DEFAULT 'US' NOT NULL,
    "IS_ACTIVE" NUMBER(1) DEFAULT 1 NOT NULL,
    "SIGNED_UP" DATE,
    "CREATED_AT" TIMESTAMP(0) WITH TIME ZONE DEFAULT SYSTIMESTAMP NOT NULL,
    "ROW_VERSION" RAW(8),
    CONSTRAINT "CK_CUSTOMERS_IS_ACTIVE" CHECK ("IS_ACTIVE" IN (0, 1))
);

BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
1,
'Ana Martínez',
'ana@example.com',
'MX',
1,
DATE '2023-01-15',
TIMESTAMP '2023-01-15 04:24:00.0000000 -06:00'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
2,
'Zoë Müller',
'zoe@example.de',
'DE',
1,
DATE '2023-02-03',
TIMESTAMP '2023-02-03 09:11:42.0000000 +01:00'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
3,
'José Peña',
'jose@example.es',
'ES',
0,
DATE '2023-03-21',
TIMESTAMP '2023-03-21 20:05:17.0000000 +01:00'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
4,
'李雷',
'lilei@example.cn',
'CN',
1,
DATE '2023-05-09',
TIMESTAMP '2023-05-09 10:40:00.0000000 +08:00'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
5,
'Noah O''Brien',
'noah@example.ie',
'IE',
1,
NULL,
TIMESTAMP '2023-06-30 15:00:00.0000000 +01:00'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
6,
'Amélie Laurent',
'amelie@example.fr',
'FR',
1,
DATE '2024-01-02',
TIMESTAMP '2024-01-02 10:30:00.0000000 +01:00'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
7,
'Ravi Patel',
'ravi@example.in',
'IN',
0,
DATE '2024-02-29',
TIMESTAMP '2024-03-01 05:29:59.0000000 +05:30'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
8,
'Sofia Rossi 🌻',
'sofia@example.it',
'IT',
1,
DATE '2024-04-12',
TIMESTAMP '2024-04-12 14:12:12.0000000 +02:00'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
1,
1,
'shipped',
129.9000,
3,
TIMESTAMP '2024-03-01 10:00:00.0000000',
TIMESTAMP '2024-03-02 16:30:00.1234567',
NULL,
'{"gift": false}',
'0b7a4c2e-3f1d-4e8a-9c55-1a2b3c4d5e6f'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
2,
2,
'paid',
54.0000,
1,
TIMESTAMP '2024-03-02 11:15:00.0000000',
NULL,
'Gift wrap 🎁',
'{"gift": true, "wrap": "red"}',
'1c8b5d3f-4a2e-4f9b-8d66-2b3c4d5e6f70'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
3,
1,
'cancelled',
12.5000,
1,
TIMESTAMP '2024-03-03 09:45:00.0000000',
NULL,
'Customer changed their mind',
NULL,
'2d9c6e4a-5b3f-4a0c-9e77-3c4d5e6f7081'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
4,
4,
'shipped',
980.0000,
12,
TIMESTAMP '2024-03-05 02:10:00.0000000',
TIMESTAMP '2024-03-07 08:00:00.0000000',
'请小心轻放',
'{"fragile": true}',
'3e0d7f5b-6c4a-4b1d-8f88-4d5e6f708192'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
5,
5,
'pending',
45.7500,
2,
TIMESTAMP '2024-03-08 17:20:00.0000000',
NULL,
'Leave at the door; ring twice',
NULL,
'4f1e806c-7d5b-4c2e-9a99-5e6f708192a3'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
6,
6,
'shipped',
310.4000,
5,
TIMESTAMP '2024-03-10 13:00:00.0000000',
TIMESTAMP '2024-03-11 09:00:00.0000000',
'Fragile: "glass"',
'{"fragile": true}',
'50f2917d-8e6c-4d3f-8baa-6f708192a3b4'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
7,
8,
'paid',
76.2000,
2,
TIMESTAMP '2024-03-11 18:45:00.0000000',
NULL,
NULL,
NULL,
'6103a28e-9f7d-4e40-9cbb-708192a3b4c5'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
8,
2,
'shipped',
19.9900,
1,
TIMESTAMP '2024-03-12 08:00:00.0000000',
TIMESTAMP '9999-12-31 23:59:59.9999999',
'Shipped date set to the maximum by an old import',
NULL,
'7214b39f-a08e-4f51-8dcc-8192a3b4c5d6'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
9,
3,
'shipped',
64.0000,
2,
TIMESTAMP '2024-03-14 15:30:00.0000000',
TIMESTAMP '2024-03-15 10:00:00.0000000',
'Two parcels',
'{"parcels": [1, 2]}',
'8325c4a0-b19f-4062-9edd-92a3b4c5d6e7'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"DETAILS",
"ORDER_REF"
) VALUES (
10,
7,
'paid',
1499.0000,
1,
TIMESTAMP '2024-03-15 21:05:00.0000000',
NULL,
'C:\Users\ravi\invoice.pdf',
NULL,
'9436d5b1-c2a0-4173-8fee-a3b4c5d6e7f8'
);
COMMIT;
END;
/

-- Keys, indexes, foreign keys, counters and triggers, after the rows.
ALTER TABLE "ORDERS" ADD CONSTRAINT "PK_ORDERS" PRIMARY KEY ("ID");
ALTER TABLE "CUSTOMERS" ADD CONSTRAINT "PK_CUSTOMERS" PRIMARY KEY ("ID");
ALTER TABLE "CUSTOMERS" ADD CONSTRAINT "UQ_CUSTOMERS_EMAIL" UNIQUE ("EMAIL");
CREATE INDEX "IX_ORDERS_IDX_ORDERS_CUSTOMER" ON "ORDERS" ("CUSTOMER_ID");
CREATE INDEX "IX_ORDERS_IDX_ORDERS_STATUS_DATE" ON "ORDERS" ("STATUS", "ORDERED_AT");
ALTER TABLE "ORDERS" ADD CONSTRAINT "FK_ORDERS" FOREIGN KEY ("CUSTOMER_ID") REFERENCES "CUSTOMERS" ("ID") ENABLE NOVALIDATE;
BEGIN
    EXECUTE IMMEDIATE 'ALTER TABLE "ORDERS" ENABLE VALIDATE CONSTRAINT "FK_ORDERS"';
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('Foreign key ' || '"FK_ORDERS"' || ' has rows without a parent: it stays unvalidated, and new rows are checked.');
END;
/
DECLARE
    next_id NUMBER;
BEGIN
    SELECT NVL(MAX("ID"), 0) + 1 INTO next_id FROM "ORDERS";
    IF next_id < 1 THEN
        next_id := 1;
    END IF;
    EXECUTE IMMEDIATE 'ALTER TABLE "ORDERS" MODIFY ("ID" GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH ' || next_id || '))';
END;
/
DECLARE
    next_id NUMBER;
BEGIN
    SELECT NVL(MAX("ID"), 0) + 1 INTO next_id FROM "CUSTOMERS";
    IF next_id < 1 THEN
        next_id := 1;
    END IF;
    EXECUTE IMMEDIATE 'ALTER TABLE "CUSTOMERS" MODIFY ("ID" GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH ' || next_id || '))';
END;
/
COMMENT ON TABLE "CUSTOMERS" IS 'People who bought at least once';
DROP FUNCTION "INTOSQL_CLOB";
DROP FUNCTION "INTOSQL_BLOB";
COMMIT;
EXIT;

Исправления

  1. "total_with_tax" таблицы orders хранится в источнике; Oracle вычисляет его при чтении.
  2. "row_version" таблицы customers - это версия строки, которую SQL Server задает сам; в дампе нет ее значений, поэтому это RAW(8), и столбец пуст.

Требует проверки

  • 6 текстовых столбцов сравнивают значения без учета регистра в источнике; Oracle сравнивает точно, поэтому уникальные ключи и поиск могут работать иначе. Используйте сопоставление или тип столбца без учета регистра для столбцов, которым это нужно.
  • Не конвертированы представления, триггеры, процедуры и события (2 объекта); отчет перечисляет каждый. Создайте их заново вручную в Oracle.
  • Проверку check1 таблицы orders нельзя записать для Oracle (function isjson), поэтому она не создана. Запишите проверку вручную, если она важна.
  • Индекс idx_orders_pending таблицы orders использует выражение, которое нельзя записать для Oracle (filtered index), поэтому он не создан. Создайте индекс вручную, если он нужен запросам.
  • Значение по умолчанию столбца "order_ref" таблицы orders нельзя записать для Oracle (function uuid), поэтому у столбца его нет. Добавьте значение по умолчанию вручную, если оно нужно новым строкам.

Файл конвертируется на этом компьютере и никуда не загружается.

Другие примеры:

Что меняется при переходе с SQL Server на Oracle

Каждая строка - это правило, которое применяет конвертер, и строка отчета, которую он пишет, когда правило что-то меняет в ваших данных.

  • bit

    NUMBER(1) с CHECK на 0 и 1

    В Oracle 21c нет логического типа столбца; 1 и 0 сохраняют значения во всех версиях.

  • char(n), varchar(n), nchar(n), nvarchar(n)

    VARCHAR2(n CHAR), длина в символах

    Длина считается в символах, как у nvarchar в SQL Server.

  • varchar(max), nvarchar(max), text, ntext

    VARCHAR2(4000 CHAR), если каждое значение укладывается в 4000 байт, иначе CLOB

    VARCHAR2 по умолчанию вмещает 4000 байт, а Oracle не может индексировать CLOB, поэтому text остается VARCHAR2, если значения помещаются, и становится CLOB, если нет.

    Строка отчета: text_as_lob

  • empty strings and empty binary values

    NULL

    Oracle хранит пустую строку как NULL, поэтому значение ' читается обратно как NULL. Отчет подсчитывает их по столбцам.

    Строка отчета: empty_string_null

  • decimal(p,s), money, smallmoney

    NUMBER(p,s); money как NUMBER(19,4)

    NUMBER вмещает 38 цифр, как и decimal, поэтому каждое значение точное.

  • datetime, datetime2, smalldatetime

    TIMESTAMP(p)

    datetime - это показание часов, как TIMESTAMP в Oracle, который хранит до девяти цифр долей секунды. date становится DATE, который хранит и время суток, оно остается полночью.

  • datetimeoffset

    TIMESTAMP WITH TIME ZONE со смещением каждого значения

    Oracle хранит смещения от -12:00 до +14:00; значение со смещением за пределами -12:00 записывается в UTC, тот же момент.

  • time

    INTERVAL DAY TO SECOND от полуночи

    В Oracle нет типа для времени суток; интервал от полуночи вмещает любое значение.

  • dates that aren't valid

    NULL

    Значение, которое не является датой, становится NULL, и отчет его подсчитывает.

    Строка отчета: date_out_of_range

  • json (SQL Server 2025)

    CLOB

    Те же значения JSON, которые читают функции JSON в Oracle.

  • uniqueidentifier

    VARCHAR2(36)

    Те же идентификаторы, записанные строчными буквами.

  • binary, varbinary, image

    RAW(n) и BLOB

    Байты остаются байтами.

  • geometry, geography

    BLOB с собственными байтами SQL Server

    SSMS записывает пространственные значения в сериализации SQL Server, которая сохраняется байт в байт.

    Строка отчета: spatial_as_native

  • rowversion, timestamp

    BLOB, пустой

    SQL Server сам задает версию строки, и SSMS не записывает для нее значений.

    Строка отчета: rowversion_empty

  • xml, sql_variant, hierarchyid, vector

    VARCHAR2 или CLOB с текстом каждого значения

    В Oracle нет равнозначного типа; xml и sql_variant сохраняют текст каждого значения, а hierarchyid - свой путь, например /1/2/.

    Строка отчета: type_replaced

  • collations that ignore case (_CI_)

    точное сравнение

    Oracle сравнивает текст точно, если не указано иное, поэтому столбцы, которые в SQL Server не учитывали регистр, теперь различают Ana и ana.

    Строка отчета: case_insensitive_collation

  • IDENTITY

    GENERATED BY DEFAULT ON NULL AS IDENTITY, продолжается после наибольшего id

    Скопированные id загружаются как есть, а счетчик продолжается после наибольшего.

  • CREATE SEQUENCE

    CREATE SEQUENCE с теми же параметрами

    Последовательности в Oracle работают так же. SSMS не записывает, до какого значения дошла последовательность, поэтому она начинается с того, с чего была создана.

  • computed columns

    виртуальные столбцы

    Oracle вычисляет генерируемые столбцы только при чтении; столбцы PERSISTED становятся виртуальными с теми же значениями.

    Строка отчета: stored_as_virtual

  • computed columns with functions Oracle lacks

    обычный столбец

    Формула, которую нельзя записать, оставляет обычный столбец и строку в отчете; SSMS не записывает значения вычисляемых столбцов.

    Строка отчета: generated_not_translated

  • defaults with functions Oracle lacks, and NEXT VALUE FOR

    без значения по умолчанию

    Значение по умолчанию, которое нельзя записать, опускается и попадает в отчет.

    Строка отчета: default_not_translated

  • CHECK constraints

    переводится

    Те же проверки, применяемые при загрузке каждой строки.

  • CHECK constraints with functions Oracle lacks

    не создается

    Проверка, которую нельзя записать, опускается и попадает в отчет.

    Строка отчета: check_skipped

  • CHECK constraints added WITH NOCHECK or disabled

    не создается

    SQL Server не применяет эти проверки, поэтому строки могут их нарушать.

    Строка отчета: check_not_enforced

  • filtered and columnstore indexes, and indexes on CLOB columns

    не создается

    IntoSQL создает индексы b-tree по целым столбцам; остальные создайте заново после загрузки.

    Строка отчета: index_skipped

  • foreign keys

    после данных ENABLE NOVALIDATE, затем валидация с предупреждением о строках без родителя

    Ключ сразу проверяет новые строки, а валидация идет последней; при строках без родителя он остается невалидированным с предупреждением, и загрузка не останавливается.

  • ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULT

    удаляется

    Внешние ключи в Oracle действуют только при удалении, с CASCADE или SET NULL.

    Строка отчета: foreign_key_action_unsupported

  • names over 128 bytes

    сокращается

    Имена в Oracle 12.2 и новее вмещают 128 байт, а в SQL Server - 128 символов.

    Строка отчета: name_shortened

  • foreign keys to tables the dump doesn't create

    не создается

    Ключ не может ссылаться на таблицу, которой нет.

    Строка отчета: foreign_key_skipped

  • tables on a partition scheme

    одна таблица со строками всех секций

    Строки те же; при необходимости секционируйте таблицу заново в Oracle.

    Строка отчета: partitions_dropped

  • temporal tables (SYSTEM_VERSIONING)

    две таблицы: текущие строки и история

    Таблица и ее таблица истории копируются как обычные таблицы; Oracle не ведет историю сам.

    Строка отчета: system_versioning_dropped

  • schemas

    одна схема, имя таблицы начинается с имени ее схемы

    Скрипт загружается в схему пользователя, который его запускает, поэтому имена таблиц из разных схем начинаются с имени схемы; таблицы из dbo сохраняют свои имена.

    Строка отчета: schemas_merged

  • NOT NULL columns with values that become NULL

    NOT NULL снимается

    Столбец, значения которого пришлось заменить на NULL, не может сохранить NOT NULL, иначе загрузка остановится.

    Строка отчета: not_null_relaxed

  • views, functions, procedures, triggers, synonyms, types and partition functions

    перечисляются в отчете

    Их код написан на T-SQL, поэтому они перечислены, чтобы вы создали их заново.

    Строка отчета: not_converted_objects

  • scripts without CREATE TABLE (data only)

    типы определяются по значениям

    Скрипт только с данными содержит лишь строки, поэтому типы берутся из значений.

    Строка отчета: no_schema

  • expressions in INSERT values

    NULL

    Конвертер, который не запускает базу данных, не может их вычислить.

    Строка отчета: expression_value

  • types IntoSQL doesn't know

    CLOB

    Тип text вмещает любое значение; измените тип после загрузки.

    Строка отчета: unknown_type

  • NUL characters in text

    сохраняется

    VARCHAR2 и CLOB могут содержать символ NUL, поэтому значение копируется как есть.

  • text that isn't valid in its encoding

    неверные байты заменяются символом замены

    Скрипт в UTF-8, и каждое значение должно быть корректным текстом.

    Строка отчета: invalid_utf8_replaced

  • text decoded twice (ñ)

    копируется как есть

    Скрипт содержит именно эти символы, поэтому они копируются; отчет на них указывает.

    Строка отчета: mojibake_suspected

В SQL ServerВ OracleСтрока отчета
bitNUMBER(1) с CHECK на 0 и 1В Oracle 21c нет логического типа столбца; 1 и 0 сохраняют значения во всех версиях.
char(n), varchar(n), nchar(n), nvarchar(n)VARCHAR2(n CHAR), длина в символахДлина считается в символах, как у nvarchar в SQL Server.
varchar(max), nvarchar(max), text, ntextVARCHAR2(4000 CHAR), если каждое значение укладывается в 4000 байт, иначе CLOBVARCHAR2 по умолчанию вмещает 4000 байт, а Oracle не может индексировать CLOB, поэтому text остается VARCHAR2, если значения помещаются, и становится CLOB, если нет.text_as_lob
empty strings and empty binary valuesNULLOracle хранит пустую строку как NULL, поэтому значение ' читается обратно как NULL. Отчет подсчитывает их по столбцам.empty_string_null
decimal(p,s), money, smallmoneyNUMBER(p,s); money как NUMBER(19,4)NUMBER вмещает 38 цифр, как и decimal, поэтому каждое значение точное.
datetime, datetime2, smalldatetimeTIMESTAMP(p)datetime - это показание часов, как TIMESTAMP в Oracle, который хранит до девяти цифр долей секунды. date становится DATE, который хранит и время суток, оно остается полночью.
datetimeoffsetTIMESTAMP WITH TIME ZONE со смещением каждого значенияOracle хранит смещения от -12:00 до +14:00; значение со смещением за пределами -12:00 записывается в UTC, тот же момент.
timeINTERVAL DAY TO SECOND от полуночиВ Oracle нет типа для времени суток; интервал от полуночи вмещает любое значение.
dates that aren't validNULLЗначение, которое не является датой, становится NULL, и отчет его подсчитывает.date_out_of_range
json (SQL Server 2025)CLOBТе же значения JSON, которые читают функции JSON в Oracle.
uniqueidentifierVARCHAR2(36)Те же идентификаторы, записанные строчными буквами.
binary, varbinary, imageRAW(n) и BLOBБайты остаются байтами.
geometry, geographyBLOB с собственными байтами SQL ServerSSMS записывает пространственные значения в сериализации SQL Server, которая сохраняется байт в байт.spatial_as_native
rowversion, timestampBLOB, пустойSQL Server сам задает версию строки, и SSMS не записывает для нее значений.rowversion_empty
xml, sql_variant, hierarchyid, vectorVARCHAR2 или CLOB с текстом каждого значенияВ Oracle нет равнозначного типа; xml и sql_variant сохраняют текст каждого значения, а hierarchyid - свой путь, например /1/2/.type_replaced
collations that ignore case (_CI_)точное сравнениеOracle сравнивает текст точно, если не указано иное, поэтому столбцы, которые в SQL Server не учитывали регистр, теперь различают Ana и ana.case_insensitive_collation
IDENTITYGENERATED BY DEFAULT ON NULL AS IDENTITY, продолжается после наибольшего idСкопированные id загружаются как есть, а счетчик продолжается после наибольшего.
CREATE SEQUENCECREATE SEQUENCE с теми же параметрамиПоследовательности в Oracle работают так же. SSMS не записывает, до какого значения дошла последовательность, поэтому она начинается с того, с чего была создана.
computed columnsвиртуальные столбцыOracle вычисляет генерируемые столбцы только при чтении; столбцы PERSISTED становятся виртуальными с теми же значениями.stored_as_virtual
computed columns with functions Oracle lacksобычный столбецФормула, которую нельзя записать, оставляет обычный столбец и строку в отчете; SSMS не записывает значения вычисляемых столбцов.generated_not_translated
defaults with functions Oracle lacks, and NEXT VALUE FORбез значения по умолчаниюЗначение по умолчанию, которое нельзя записать, опускается и попадает в отчет.default_not_translated
CHECK constraintsпереводитсяТе же проверки, применяемые при загрузке каждой строки.
CHECK constraints with functions Oracle lacksне создаетсяПроверка, которую нельзя записать, опускается и попадает в отчет.check_skipped
CHECK constraints added WITH NOCHECK or disabledне создаетсяSQL Server не применяет эти проверки, поэтому строки могут их нарушать.check_not_enforced
filtered and columnstore indexes, and indexes on CLOB columnsне создаетсяIntoSQL создает индексы b-tree по целым столбцам; остальные создайте заново после загрузки.index_skipped
foreign keysпосле данных ENABLE NOVALIDATE, затем валидация с предупреждением о строках без родителяКлюч сразу проверяет новые строки, а валидация идет последней; при строках без родителя он остается невалидированным с предупреждением, и загрузка не останавливается.
ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULTудаляетсяВнешние ключи в Oracle действуют только при удалении, с CASCADE или SET NULL.foreign_key_action_unsupported
names over 128 bytesсокращаетсяИмена в Oracle 12.2 и новее вмещают 128 байт, а в SQL Server - 128 символов.name_shortened
foreign keys to tables the dump doesn't createне создаетсяКлюч не может ссылаться на таблицу, которой нет.foreign_key_skipped
tables on a partition schemeодна таблица со строками всех секцийСтроки те же; при необходимости секционируйте таблицу заново в Oracle.partitions_dropped
temporal tables (SYSTEM_VERSIONING)две таблицы: текущие строки и историяТаблица и ее таблица истории копируются как обычные таблицы; Oracle не ведет историю сам.system_versioning_dropped
schemasодна схема, имя таблицы начинается с имени ее схемыСкрипт загружается в схему пользователя, который его запускает, поэтому имена таблиц из разных схем начинаются с имени схемы; таблицы из dbo сохраняют свои имена.schemas_merged
NOT NULL columns with values that become NULLNOT NULL снимаетсяСтолбец, значения которого пришлось заменить на NULL, не может сохранить NOT NULL, иначе загрузка остановится.not_null_relaxed
views, functions, procedures, triggers, synonyms, types and partition functionsперечисляются в отчетеИх код написан на T-SQL, поэтому они перечислены, чтобы вы создали их заново.not_converted_objects
scripts without CREATE TABLE (data only)типы определяются по значениямСкрипт только с данными содержит лишь строки, поэтому типы берутся из значений.no_schema
expressions in INSERT valuesNULLКонвертер, который не запускает базу данных, не может их вычислить.expression_value
types IntoSQL doesn't knowCLOBТип text вмещает любое значение; измените тип после загрузки.unknown_type
NUL characters in textсохраняетсяVARCHAR2 и CLOB могут содержать символ NUL, поэтому значение копируется как есть.
text that isn't valid in its encodingневерные байты заменяются символом заменыСкрипт в UTF-8, и каждое значение должно быть корректным текстом.invalid_utf8_replaced
text decoded twice (ñ)копируется как естьСкрипт содержит именно эти символы, поэтому они копируются; отчет на них указывает.mojibake_suspected

Загрузите скрипт в Oracle

Скрипт создает таблицы, копирует строки, затем добавляет ключи, индексы и внешние ключи, поэтому загрузка идет быстро и останавливается на первой ошибке.

NLS_LANG=.AL32UTF8 sqlplus -S -L user@//localhost/mydb @sql_server.oracle.sql

Внешние ключи добавляются ENABLE NOVALIDATE, поэтому новые строки проверяются сразу, а затем выполняется валидация. Если старая строка ссылается на несуществующую строку, скрипт сообщает, какое это ограничение, и оставляет его без валидации, а не прерывается на полпути.

Для большого дампа запускайте SQL*Plus на той же машине, где работает база данных. Скрипт фиксирует каждые 100 строк. Пользователю, который его запускает, нужны CREATE TABLE, CREATE SEQUENCE, CREATE TRIGGER и CREATE PROCEDURE, а также квота в его табличном пространстве.

Как создать дамп SQL Server для лучшего результата

Конвертер читает то, что есть в дампе. Эти параметры сохраняют в нем больше ваших данных:

  • В SSMS щелкните базу данных правой кнопкой, выберите Tasks, Generate Scripts и отметьте таблицы. dbatools, mssql-scripter и другие инструменты на той же библиотеке пишут такой же скрипт.
  • В разделе Advanced задайте для Types of data to script значение Schema and data. Скрипт только со схемой содержит таблицы без строк.
  • Сохраните его в Unicode, как по умолчанию в SSMS, или в UTF-8: оба читаются одинаково, gzip тоже подходит.

Что не конвертируется

Представления, функции, процедуры, триггеры, синонимы, правила и политики безопасности написаны на T-SQL. Они перечислены в отчете по имени и никогда не удаляются молча, чтобы вы могли переписать их для Oracle.

Вопросы о SQL Server в Oracle

Нет ответа на ваш вопрос? Напишите нам через страницу контактов, и вам ответит человек. Страница контактов

Мой дамп загружается на сервер?

Нет. Конвертер работает в вашем браузере и читает дамп с диска по частям, поэтому он никогда не покидает ваш компьютер. Приложение для компьютера и командная строка тоже конвертируют на вашем компьютере.

Насколько большим может быть дамп?

Конвертер никогда не держит весь дамп в памяти: он читает файл дважды, по диапазонам, и пишет скрипт по ходу чтения. Дампы в несколько гигабайт конвертируются в браузере, в приложении для компьютера и в командной строке.

Читает ли он файл UTF-16, который сохраняет SSMS?

Да. SSMS по умолчанию сохраняет скрипты в UTF-16, а конвертер одинаково читает UTF-16 и UTF-8, сжатые gzip или нет, с GO между пакетами.

Из каких версий SQL Server может быть скрипт?

Скрипты, которые SSMS, dbatools или mssql-scripter пишут из SQL Server 2017 и новее. Каждый тестовый скрипт создан в SQL Server 2017, 2022 и 2025 и сверен с источником ячейка за ячейкой.

Сохраняются ли значения IDENTITY?

Да. Столбцы IDENTITY становятся столбцами identity, каждая строка сохраняет свой id, а следующий id идет после наибольшего. Последовательности создаются с теми же параметрами.

Что происходит с money, datetimeoffset и другими типами SQL Server?

bit становится NUMBER(1), datetime2 - TIMESTAMP со всеми цифрами, datetimeoffset - TIMESTAMP WITH TIME ZONE со своим смещением, а nvarchar(max) - CLOB, если значения не помещаются в VARCHAR2. Пустые строки становятся NULL, как их хранит Oracle, и отчет их подсчитывает.

А процедуры, триггеры и представления?

Они перечислены в отчете по имени и не конвертируются, потому что каждая база данных пишет их на своем языке.

На каких версиях Oracle загружается скрипт?

Oracle 19c и новее. Каждый тестовый скрипт загружается на 21c и 23ai и останавливается на первой ошибке, если что-то пойдет не так.