Przejdź do treści
Strona główna IntoSQL

Konwertuj SQL Server do Oracle

Upuść skrypt, który Generate Scripts w SSMS zapisuje ze schematem i danymi, jako .sql lub .sql.gz, w UTF-16 lub UTF-8, i pobierz skrypt Oracle z tymi samymi tabelami, kluczami, indeksami i danymi. Każda wartość, której Oracle nie może przechować bez zmian, i każdy obiekt, którego nie przenosi, są wymienione w raporcie.

Twój plik
sqlshop_2024_sqlserver.sqlPlik przykładowy, 11 kB
Twoja baza danych

18 wierszy przekonwertowanych, 2 poprawki, brak odrzuconych

Pokaż

Tabele w pliku shop_2024_sqlserver.sqlZrzut SQL Server · zapisany przez SQL Server Management Objects · utf-8

  • orderszapisana jako ORDERS10 wierszy1
    11 kolumn
    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)
  • customerszapisana jako CUSTOMERS8 wierszy1
    8 kolumn
    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)

Nieprzekonwertowane

  • Widok paid_orders
  • Wyzwalacz orders_no_negative

Każda baza danych zapisuje je we własnym języku. Przepisz je dla 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;

Poprawki

  1. "total_with_tax" w tabeli orders jest w źródle przechowywana; Oracle oblicza ją przy odczycie.
  2. "row_version" w tabeli customers to wersja wiersza, którą SQL Server ustawia sam; zrzut nie ma dla niej wartości, więc ma typ RAW(8) i jest pusta.

Do sprawdzenia

  • W źródle 6 kolumn tekstowych ignoruje wielkość liter przy porównaniu; Oracle porównuje dokładnie, więc klucze unikalne i wyszukiwanie mogą działać inaczej. Użyj collation lub typu kolumny ignorującego wielkość liter w kolumnach, które tego potrzebują.
  • Widoki, wyzwalacze, procedury i zdarzenia nie są konwertowane: 2 obiekty, każdy wymieniony w raporcie. Utwórz je ręcznie w Oracle.
  • Ograniczenia CHECK check1 w tabeli orders nie da się zapisać dla Oracle (function isjson), więc go nie utworzono. Zapisz ograniczenie CHECK ręcznie, jeśli jest ważne.
  • Indeks idx_orders_pending w tabeli orders używa wyrażenia, którego nie da się zapisać dla Oracle (filtered index), więc go nie utworzono. Utwórz indeks ręcznie, jeśli zapytania go potrzebują.
  • Wartości domyślnej "order_ref" w tabeli orders nie da się zapisać dla Oracle (function uuid), więc kolumna nie ma wartości domyślnej. Dodaj wartość domyślną ręcznie, jeśli nowe wiersze jej potrzebują.

Plik jest konwertowany na tym komputerze i nigdy nie jest wysyłany.

Inne przykłady:

Co zmienia się między SQL Server a Oracle

Każdy wiersz to reguła stosowana przez konwerter, z wpisem, który dodaje do raportu, gdy reguła coś zmienia w twoich danych.

  • bit

    NUMBER(1) z CHECK 0 i 1

    Oracle 21c nie ma typu kolumny logicznej; 1 i 0 zachowują wartości w każdej wersji.

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

    VARCHAR2(n CHAR), liczony w znakach

    Długości liczą znaki, tak jak nvarchar w SQL Server.

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

    VARCHAR2(4000 CHAR), gdy każda wartość mieści się w 4000 bajtach, w przeciwnym razie CLOB

    VARCHAR2 mieści domyślnie 4000 bajtów, a Oracle nie indeksuje CLOB, więc tekst zostaje VARCHAR2, gdy jego wartości się mieszczą, a CLOB, gdy nie.

    Wpis w raporcie: text_as_lob

  • empty strings and empty binary values

    NULL

    Oracle zapisuje pusty ciąg jako NULL, więc wartość ' jest odczytywana jako NULL. Raport liczy je w każdej kolumnie.

    Wpis w raporcie: empty_string_null

  • decimal(p,s), money, smallmoney

    NUMBER(p,s); money jako NUMBER(19,4)

    NUMBER mieści 38 cyfr, tak jak decimal, więc każda wartość jest dokładna.

  • datetime, datetime2, smalldatetime

    TIMESTAMP(p)

    datetime to wskazanie zegara, jak TIMESTAMP w Oracle, który zachowuje do dziewięciu cyfr ułamka sekundy. date staje się DATE, który zawiera też godzinę, ustawioną na północ.

  • datetimeoffset

    TIMESTAMP WITH TIME ZONE z przesunięciem każdej wartości

    Oracle przechowuje przesunięcia od -12:00 do +14:00; wartość z przesunięciem poza -12:00 jest zapisywana w UTC, ten sam moment.

  • time

    INTERVAL DAY TO SECOND od północy

    Oracle nie ma typu godziny dnia; interwał od północy mieści każdą wartość.

  • dates that aren't valid

    NULL

    Wartość, która nie jest datą, staje się NULL, a raport ją liczy.

    Wpis w raporcie: date_out_of_range

  • json (SQL Server 2025)

    CLOB

    Te same wartości JSON, które odczytują funkcje JSON w Oracle.

  • uniqueidentifier

    VARCHAR2(36)

    Te same identyfikatory, zapisane małymi literami.

  • binary, varbinary, image

    RAW(n) i BLOB

    Bajty pozostają bajtami.

  • geometry, geography

    BLOB z własnymi bajtami SQL Server

    SSMS zapisuje wartości przestrzenne w serializacji SQL Server, zachowywanej bajt po bajcie.

    Wpis w raporcie: spatial_as_native

  • rowversion, timestamp

    BLOB, pusty

    SQL Server sam ustawia wersję wiersza, a SSMS nie zapisuje dla niej wartości.

    Wpis w raporcie: rowversion_empty

  • xml, sql_variant, hierarchyid, vector

    VARCHAR2 lub CLOB z tekstem każdej wartości

    Oracle nie ma odpowiedniego typu; xml i sql_variant zachowują tekst każdej wartości, a hierarchyid swoją ścieżkę, np. /1/2/.

    Wpis w raporcie: type_replaced

  • collations that ignore case (_CI_)

    dokładne porównanie

    Oracle porównuje tekst dokładnie, chyba że ustawisz inaczej, więc kolumny, które w SQL Server ignorowały wielkość liter, teraz odróżniają Ana od ana.

    Wpis w raporcie: case_insensitive_collation

  • IDENTITY

    GENERATED BY DEFAULT ON NULL AS IDENTITY, kontynuowane po najwyższym id

    Skopiowane id ładują się bez zmian, a licznik idzie dalej po najwyższym.

  • CREATE SEQUENCE

    CREATE SEQUENCE z tymi samymi opcjami

    Sekwencje w Oracle działają tak samo. SSMS nie zapisuje, dokąd doszła sekwencja, więc zaczyna ona od wartości, od której została utworzona.

  • computed columns

    kolumny wirtualne

    Oracle oblicza kolumny generowane tylko przy odczycie; kolumny PERSISTED stają się wirtualne z tymi samymi wartościami.

    Wpis w raporcie: stored_as_virtual

  • computed columns with functions Oracle lacks

    zwykła kolumna

    Formuła, której nie da się zapisać, zostawia zwykłą kolumnę i wpis w raporcie; SSMS nie zapisuje wartości kolumn obliczanych.

    Wpis w raporcie: generated_not_translated

  • defaults with functions Oracle lacks, and NEXT VALUE FOR

    brak wartości domyślnej

    Wartość domyślna, której nie da się zapisać, jest pomijana i zgłaszana w raporcie.

    Wpis w raporcie: default_not_translated

  • CHECK constraints

    przetłumaczone

    Te same ograniczenia CHECK, sprawdzane przy ładowaniu każdego wiersza.

  • CHECK constraints with functions Oracle lacks

    nie jest tworzone

    Ograniczenie CHECK, którego nie da się zapisać, jest pomijane i zgłaszane w raporcie.

    Wpis w raporcie: check_skipped

  • CHECK constraints added WITH NOCHECK or disabled

    nie jest tworzone

    SQL Server nie stosuje tych ograniczeń CHECK, więc wiersze mogą je łamać.

    Wpis w raporcie: check_not_enforced

  • filtered and columnstore indexes, and indexes on CLOB columns

    nie jest tworzone

    IntoSQL zapisuje indeksy b-tree na całych kolumnach; pozostałe utwórz ponownie po załadowaniu.

    Wpis w raporcie: index_skipped

  • foreign keys

    po danych z ENABLE NOVALIDATE, potem walidowany z ostrzeżeniem o osieroconych wierszach

    Klucz od razu sprawdza nowe wiersze i jest walidowany na końcu; wiersze bez rodzica zostawiają go niezwalidowanym z ostrzeżeniem, zamiast zatrzymać ładowanie.

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

    usunięte

    Klucze obce w Oracle działają tylko przy usuwaniu, z CASCADE lub SET NULL.

    Wpis w raporcie: foreign_key_action_unsupported

  • names over 128 bytes

    skrócone

    Nazwy w Oracle 12.2 i nowszym mają do 128 bajtów; w SQL Server do 128 znaków.

    Wpis w raporcie: name_shortened

  • foreign keys to tables the dump doesn't create

    nie jest tworzone

    Klucz nie może wskazywać tabeli, której nie ma.

    Wpis w raporcie: foreign_key_skipped

  • tables on a partition scheme

    jedna tabela z wierszami wszystkich partycji

    Wiersze są te same; jeśli trzeba, podziel tabelę na partycje ponownie w Oracle.

    Wpis w raporcie: partitions_dropped

  • temporal tables (SYSTEM_VERSIONING)

    dwie tabele: bieżące wiersze i historia

    Tabela i jej tabela historii są kopiowane jako zwykłe tabele; Oracle nie przechowuje historii sam.

    Wpis w raporcie: system_versioning_dropped

  • schemas

    jeden schemat, nazwa każdej tabeli zaczyna się od nazwy jej schematu

    Skrypt ładuje się do schematu użytkownika, który go uruchamia, więc nazwy tabel z różnych schematów zaczynają się od nazwy schematu; tabele z dbo zachowują nazwy.

    Wpis w raporcie: schemas_merged

  • NOT NULL columns with values that become NULL

    NOT NULL usunięte

    Kolumna, której wartości musiały stać się NULL, nie może zachować NOT NULL, bo ładowanie by się zatrzymało.

    Wpis w raporcie: not_null_relaxed

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

    wymienione w raporcie

    Ich kod jest napisany w T-SQL, więc trafiają na listę do ręcznego odtworzenia.

    Wpis w raporcie: not_converted_objects

  • scripts without CREATE TABLE (data only)

    typy odczytane z wartości

    Skrypt samych danych zawiera tylko wiersze, więc typy pochodzą z wartości.

    Wpis w raporcie: no_schema

  • expressions in INSERT values

    NULL

    Konwerter, który nie uruchamia bazy danych, nie może ich obliczyć.

    Wpis w raporcie: expression_value

  • types IntoSQL doesn't know

    CLOB

    Tekst mieści każdą wartość; zmień typ po załadowaniu.

    Wpis w raporcie: unknown_type

  • NUL characters in text

    zachowane

    VARCHAR2 i CLOB mogą zawierać znak NUL, więc wartość jest kopiowana bez zmian.

  • text that isn't valid in its encoding

    błędne bajty jako znak zastępczy

    Skrypt jest w UTF-8 i każda wartość musi być poprawnym tekstem.

    Wpis w raporcie: invalid_utf8_replaced

  • text decoded twice (ñ)

    skopiowane bez zmian

    Skrypt zawiera dokładnie te znaki, więc są kopiowane; raport je wskazuje.

    Wpis w raporcie: mojibake_suspected

W SQL ServerW OracleWpis w raporcie
bitNUMBER(1) z CHECK 0 i 1Oracle 21c nie ma typu kolumny logicznej; 1 i 0 zachowują wartości w każdej wersji.
char(n), varchar(n), nchar(n), nvarchar(n)VARCHAR2(n CHAR), liczony w znakachDługości liczą znaki, tak jak nvarchar w SQL Server.
varchar(max), nvarchar(max), text, ntextVARCHAR2(4000 CHAR), gdy każda wartość mieści się w 4000 bajtach, w przeciwnym razie CLOBVARCHAR2 mieści domyślnie 4000 bajtów, a Oracle nie indeksuje CLOB, więc tekst zostaje VARCHAR2, gdy jego wartości się mieszczą, a CLOB, gdy nie.text_as_lob
empty strings and empty binary valuesNULLOracle zapisuje pusty ciąg jako NULL, więc wartość ' jest odczytywana jako NULL. Raport liczy je w każdej kolumnie.empty_string_null
decimal(p,s), money, smallmoneyNUMBER(p,s); money jako NUMBER(19,4)NUMBER mieści 38 cyfr, tak jak decimal, więc każda wartość jest dokładna.
datetime, datetime2, smalldatetimeTIMESTAMP(p)datetime to wskazanie zegara, jak TIMESTAMP w Oracle, który zachowuje do dziewięciu cyfr ułamka sekundy. date staje się DATE, który zawiera też godzinę, ustawioną na północ.
datetimeoffsetTIMESTAMP WITH TIME ZONE z przesunięciem każdej wartościOracle przechowuje przesunięcia od -12:00 do +14:00; wartość z przesunięciem poza -12:00 jest zapisywana w UTC, ten sam moment.
timeINTERVAL DAY TO SECOND od północyOracle nie ma typu godziny dnia; interwał od północy mieści każdą wartość.
dates that aren't validNULLWartość, która nie jest datą, staje się NULL, a raport ją liczy.date_out_of_range
json (SQL Server 2025)CLOBTe same wartości JSON, które odczytują funkcje JSON w Oracle.
uniqueidentifierVARCHAR2(36)Te same identyfikatory, zapisane małymi literami.
binary, varbinary, imageRAW(n) i BLOBBajty pozostają bajtami.
geometry, geographyBLOB z własnymi bajtami SQL ServerSSMS zapisuje wartości przestrzenne w serializacji SQL Server, zachowywanej bajt po bajcie.spatial_as_native
rowversion, timestampBLOB, pustySQL Server sam ustawia wersję wiersza, a SSMS nie zapisuje dla niej wartości.rowversion_empty
xml, sql_variant, hierarchyid, vectorVARCHAR2 lub CLOB z tekstem każdej wartościOracle nie ma odpowiedniego typu; xml i sql_variant zachowują tekst każdej wartości, a hierarchyid swoją ścieżkę, np. /1/2/.type_replaced
collations that ignore case (_CI_)dokładne porównanieOracle porównuje tekst dokładnie, chyba że ustawisz inaczej, więc kolumny, które w SQL Server ignorowały wielkość liter, teraz odróżniają Ana od ana.case_insensitive_collation
IDENTITYGENERATED BY DEFAULT ON NULL AS IDENTITY, kontynuowane po najwyższym idSkopiowane id ładują się bez zmian, a licznik idzie dalej po najwyższym.
CREATE SEQUENCECREATE SEQUENCE z tymi samymi opcjamiSekwencje w Oracle działają tak samo. SSMS nie zapisuje, dokąd doszła sekwencja, więc zaczyna ona od wartości, od której została utworzona.
computed columnskolumny wirtualneOracle oblicza kolumny generowane tylko przy odczycie; kolumny PERSISTED stają się wirtualne z tymi samymi wartościami.stored_as_virtual
computed columns with functions Oracle lackszwykła kolumnaFormuła, której nie da się zapisać, zostawia zwykłą kolumnę i wpis w raporcie; SSMS nie zapisuje wartości kolumn obliczanych.generated_not_translated
defaults with functions Oracle lacks, and NEXT VALUE FORbrak wartości domyślnejWartość domyślna, której nie da się zapisać, jest pomijana i zgłaszana w raporcie.default_not_translated
CHECK constraintsprzetłumaczoneTe same ograniczenia CHECK, sprawdzane przy ładowaniu każdego wiersza.
CHECK constraints with functions Oracle lacksnie jest tworzoneOgraniczenie CHECK, którego nie da się zapisać, jest pomijane i zgłaszane w raporcie.check_skipped
CHECK constraints added WITH NOCHECK or disablednie jest tworzoneSQL Server nie stosuje tych ograniczeń CHECK, więc wiersze mogą je łamać.check_not_enforced
filtered and columnstore indexes, and indexes on CLOB columnsnie jest tworzoneIntoSQL zapisuje indeksy b-tree na całych kolumnach; pozostałe utwórz ponownie po załadowaniu.index_skipped
foreign keyspo danych z ENABLE NOVALIDATE, potem walidowany z ostrzeżeniem o osieroconych wierszachKlucz od razu sprawdza nowe wiersze i jest walidowany na końcu; wiersze bez rodzica zostawiają go niezwalidowanym z ostrzeżeniem, zamiast zatrzymać ładowanie.
ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULTusunięteKlucze obce w Oracle działają tylko przy usuwaniu, z CASCADE lub SET NULL.foreign_key_action_unsupported
names over 128 bytesskróconeNazwy w Oracle 12.2 i nowszym mają do 128 bajtów; w SQL Server do 128 znaków.name_shortened
foreign keys to tables the dump doesn't createnie jest tworzoneKlucz nie może wskazywać tabeli, której nie ma.foreign_key_skipped
tables on a partition schemejedna tabela z wierszami wszystkich partycjiWiersze są te same; jeśli trzeba, podziel tabelę na partycje ponownie w Oracle.partitions_dropped
temporal tables (SYSTEM_VERSIONING)dwie tabele: bieżące wiersze i historiaTabela i jej tabela historii są kopiowane jako zwykłe tabele; Oracle nie przechowuje historii sam.system_versioning_dropped
schemasjeden schemat, nazwa każdej tabeli zaczyna się od nazwy jej schematuSkrypt ładuje się do schematu użytkownika, który go uruchamia, więc nazwy tabel z różnych schematów zaczynają się od nazwy schematu; tabele z dbo zachowują nazwy.schemas_merged
NOT NULL columns with values that become NULLNOT NULL usunięteKolumna, której wartości musiały stać się NULL, nie może zachować NOT NULL, bo ładowanie by się zatrzymało.not_null_relaxed
views, functions, procedures, triggers, synonyms, types and partition functionswymienione w raporcieIch kod jest napisany w T-SQL, więc trafiają na listę do ręcznego odtworzenia.not_converted_objects
scripts without CREATE TABLE (data only)typy odczytane z wartościSkrypt samych danych zawiera tylko wiersze, więc typy pochodzą z wartości.no_schema
expressions in INSERT valuesNULLKonwerter, który nie uruchamia bazy danych, nie może ich obliczyć.expression_value
types IntoSQL doesn't knowCLOBTekst mieści każdą wartość; zmień typ po załadowaniu.unknown_type
NUL characters in textzachowaneVARCHAR2 i CLOB mogą zawierać znak NUL, więc wartość jest kopiowana bez zmian.
text that isn't valid in its encodingbłędne bajty jako znak zastępczySkrypt jest w UTF-8 i każda wartość musi być poprawnym tekstem.invalid_utf8_replaced
text decoded twice (ñ)skopiowane bez zmianSkrypt zawiera dokładnie te znaki, więc są kopiowane; raport je wskazuje.mojibake_suspected

Załaduj skrypt do Oracle

Skrypt tworzy tabele, kopiuje wiersze, a potem dodaje klucze, indeksy i klucze obce, więc ładuje się szybko i zatrzymuje przy pierwszym błędzie.

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

Klucze obce są dodawane z ENABLE NOVALIDATE, więc nowe wiersze są sprawdzane od razu, a potem walidowane. Jeśli stary wiersz wskazuje na nieistniejący wiersz, skrypt podaje, którego ograniczenia to dotyczy, i zostawia je niezwalidowane, zamiast przerwać w połowie.

Przy dużym zrzucie uruchom SQL*Plus na tej samej maszynie co baza danych. Skrypt zatwierdza co 100 wierszy. Użytkownik, który go uruchamia, potrzebuje CREATE TABLE, CREATE SEQUENCE, CREATE TRIGGER i CREATE PROCEDURE oraz limitu w swojej przestrzeni tabel.

Jak zrobić zrzut SQL Server dla najlepszego wyniku

Konwerter odczytuje to, co zawiera zrzut. Te opcje zachowują w nim więcej twoich danych:

  • W SSMS kliknij prawym przyciskiem bazę danych, Tasks, Generate Scripts i wybierz tabele. dbatools, mssql-scripter i inne narzędzia oparte na tej samej bibliotece zapisują taki sam skrypt.
  • W sekcji Advanced ustaw Types of data to script na Schema and data. Skrypt samego schematu ma tabele bez wierszy.
  • Zapisz go jako Unicode, domyślnie w SSMS, lub jako UTF-8: oba są czytane tak samo, a gzip też działa.

Co nie jest konwertowane

Widoki, funkcje, procedury, wyzwalacze, synonimy, reguły i polityki bezpieczeństwa są pisane w T-SQL. Raport wymienia je z nazwy i nigdy nie pomija ich po cichu, więc możesz je przepisać dla Oracle.

Pytania o konwersję SQL Server do Oracle

Nie ma tu odpowiedzi? Napisz do nas przez stronę kontaktu, a odpowie człowiek. Strona kontaktu

Czy mój zrzut jest wysyłany?

Nie. Konwerter działa w przeglądarce i odczytuje zrzut z dysku po kawałku, więc nigdy nie opuszcza on twojego komputera. Aplikacja na komputer i wiersz poleceń też konwertują na twoim komputerze.

Jak duży może być zrzut?

Konwerter nigdy nie trzyma całego zrzutu w pamięci: czyta plik dwa razy, fragmentami, i zapisuje skrypt na bieżąco. Zrzuty wielogigabajtowe konwertują się w przeglądarce, w aplikacji na komputer i w wierszu poleceń.

Czy odczytuje plik UTF-16 zapisany przez SSMS?

Tak. SSMS domyślnie zapisuje skrypty jako UTF-16, a konwerter czyta UTF-16 i UTF-8 tak samo, spakowane gzip lub nie, z GO między partiami.

Z jakich wersji SQL Server może pochodzić skrypt?

Skrypty zapisane przez SSMS, dbatools lub mssql-scripter z SQL Server od wersji 2017. Każdy testowy skrypt pochodzi z SQL Server 2017, 2022 i 2025 i jest porównywany ze źródłem komórka po komórce.

Czy wartości IDENTITY są zachowywane?

Tak. Kolumny IDENTITY stają się kolumnami identity, każdy wiersz zachowuje swoje id, a kolejne id idzie po najwyższym. Sekwencje są tworzone z tymi samymi opcjami.

Co dzieje się z money, datetimeoffset i innymi typami SQL Server?

bit staje się NUMBER(1), datetime2 TIMESTAMP ze wszystkimi cyframi, datetimeoffset TIMESTAMP WITH TIME ZONE z przesunięciem, a nvarchar(max) CLOB, gdy wartości nie mieszczą się w VARCHAR2. Puste ciągi stają się NULL, bo tak przechowuje je Oracle, a raport je liczy.

A procedury, wyzwalacze i widoki?

Raport wymienia je z nazwy, ale nie są konwertowane, bo każda baza danych zapisuje je we własnym języku.

Na jakich wersjach Oracle ładuje się skrypt?

Oracle 19c i nowsze. Każdy testowy skrypt ładuje się na 21c i 23ai i zatrzymuje przy pierwszym błędzie, jeśli coś pójdzie nie tak.