Naar de inhoud
IntoSQL-startpagina

SQL Server omzetten naar Oracle

Zet het script neer dat Generate Scripts van SSMS met schema en data schrijft, als .sql of .sql.gz, UTF-16 of UTF-8, en download een Oracle-script met dezelfde tabellen, sleutels, indexen en data. Elke waarde die Oracle niet ongewijzigd kan bevatten, en elk object dat het niet overneemt, staat in het rapport.

Je bestand
sqlshop_2024_sqlserver.sqlVoorbeeldbestand, 11 kB
Je database

18 rijen geconverteerd, 2 correcties, geen afgewezen

Tonen

Tabellen in shop_2024_sqlserver.sqlSQL Server-dump · geschreven door SQL Server Management Objects · utf-8

  • ordersgeschreven als ORDERS10 rijen1
    11 kolommen
    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)
  • customersgeschreven als CUSTOMERS8 rijen1
    8 kolommen
    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)

Niet geconverteerd

  • Weergave paid_orders
  • Trigger orders_no_negative

Elke database schrijft deze in een eigen taal. Herschrijf ze voor 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;

Correcties

  1. "total_with_tax" van orders wordt in de bron opgeslagen; Oracle berekent het bij het lezen.
  2. "row_version" van customers is een rijversie die SQL Server zelf instelt; de dump heeft er geen waarden voor, dus het is RAW(8) en leeg.

Na te kijken

  • 6 tekstkolommen vergelijken in de bron zonder op hoofdletters te letten; Oracle vergelijkt exact, dus unieke sleutels en zoekopdrachten kunnen anders werken. Gebruik een collation of kolomtype dat hoofdletters negeert voor de kolommen die dat nodig hebben.
  • 2 weergaven, triggers, routines of gebeurtenissen zijn niet geconverteerd; het rapport noemt ze allemaal. Maak ze met de hand opnieuw aan in Oracle.
  • De check check1 op orders kan niet voor Oracle worden geschreven (function isjson), dus hij wordt niet aangemaakt. Schrijf de check met de hand als hij ertoe doet.
  • De index idx_orders_pending op orders gebruikt een expressie die niet voor Oracle kan worden geschreven (filtered index), dus hij wordt niet aangemaakt. Maak de index met de hand aan als query's hem nodig hebben.
  • De standaardwaarde van "order_ref" in orders kan niet voor Oracle worden geschreven (function uuid), dus de kolom heeft geen standaardwaarde. Voeg de standaardwaarde met de hand toe als nieuwe rijen die nodig hebben.

Je bestand wordt op deze computer omgezet en nooit geüpload.

Andere voorbeelden:

Wat er verandert van SQL Server naar Oracle

Elke rij is een regel die de converter toepast, met de rapportregel die hij schrijft als de regel iets in je data verandert.

  • bit

    NUMBER(1) met een CHECK op 0 en 1

    Oracle 21c heeft geen boolean-kolomtype; 1 en 0 bewaren de waarden op elke versie.

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

    VARCHAR2(n CHAR), in tekens geteld

    Lengtes tellen tekens, zoals nvarchar in SQL Server.

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

    VARCHAR2(4000 CHAR) als elke waarde in 4000 bytes past, anders CLOB

    Een VARCHAR2 bevat standaard 4000 bytes en Oracle kan een CLOB niet indexeren, dus tekst blijft VARCHAR2 als de waarden passen en wordt CLOB als ze dat niet doen.

    Rapportregel: text_as_lob

  • empty strings and empty binary values

    NULL

    Oracle slaat een lege string op als NULL, dus een waarde die ' was, wordt teruggelezen als NULL. Het rapport telt ze per kolom.

    Rapportregel: empty_string_null

  • decimal(p,s), money, smallmoney

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

    NUMBER bevat 38 cijfers, net als decimal, dus elke waarde is exact.

  • datetime, datetime2, smalldatetime

    TIMESTAMP(p)

    Een datetime is een kloktijd, net als TIMESTAMP in Oracle, dat tot negen cijfers van een seconde bewaart. date wordt DATE, dat ook een tijdstip bevat dat op middernacht blijft.

  • datetimeoffset

    TIMESTAMP WITH TIME ZONE, met de offset van elke waarde

    Oracle bewaart offsets van -12:00 tot +14:00; een waarde met een offset voorbij -12:00 wordt in UTC geschreven: hetzelfde moment.

  • time

    INTERVAL DAY TO SECOND vanaf middernacht

    Oracle heeft geen type voor een tijdstip; een interval vanaf middernacht bevat elke waarde.

  • dates that aren't valid

    NULL

    Een waarde die geen datum is, wordt NULL en het rapport telt hem.

    Rapportregel: date_out_of_range

  • json (SQL Server 2025)

    CLOB

    Dezelfde JSON-waarden, die de JSON-functies van Oracle lezen.

  • uniqueidentifier

    VARCHAR2(36)

    Dezelfde identifiers, in kleine letters geschreven.

  • binary, varbinary, image

    RAW(n) en BLOB

    Bytes blijven bytes.

  • geometry, geography

    BLOB met de eigen bytes van SQL Server

    SSMS schrijft ruimtelijke waarden in de serialisatie van SQL Server, die byte voor byte behouden blijft.

    Rapportregel: spatial_as_native

  • rowversion, timestamp

    BLOB, leeg

    SQL Server stelt een rijversie zelf in en SSMS neemt er geen waarden voor op in het script.

    Rapportregel: rowversion_empty

  • xml, sql_variant, hierarchyid, vector

    VARCHAR2 of CLOB met de tekst van elke waarde

    Oracle heeft geen gelijkwaardig type; xml en sql_variant behouden de tekst van elke waarde en hierarchyid zijn pad, zoals /1/2/.

    Rapportregel: type_replaced

  • collations that ignore case (_CI_)

    exacte vergelijking

    Oracle vergelijkt tekst exact, tenzij anders aangegeven, dus kolommen die in SQL Server hoofdletters negeerden, onderscheiden nu Ana en ana.

    Rapportregel: case_insensitive_collation

  • IDENTITY

    GENERATED BY DEFAULT ON NULL AS IDENTITY, verdergaand na het hoogste id

    De gekopieerde id's laden ongewijzigd, en de teller gaat verder na het hoogste.

  • CREATE SEQUENCE

    CREATE SEQUENCE met dezelfde opties

    Sequences in Oracle werken op dezelfde manier. SSMS legt niet vast hoe ver een sequence is gekomen, dus hij begint waar hij is aangemaakt.

  • computed columns

    virtuele kolommen

    Oracle berekent gegenereerde kolommen alleen bij het lezen; PERSISTED-kolommen worden virtueel met dezelfde waarden.

    Rapportregel: stored_as_virtual

  • computed columns with functions Oracle lacks

    een gewone kolom

    Een formule die niet kan worden geschreven, levert een gewone kolom en een regel in het rapport op; SSMS neemt geen waarden voor berekende kolommen op in het script.

    Rapportregel: generated_not_translated

  • defaults with functions Oracle lacks, and NEXT VALUE FOR

    geen standaardwaarde

    Een standaardwaarde die niet kan worden geschreven, wordt weggelaten en gemeld.

    Rapportregel: default_not_translated

  • CHECK constraints

    vertaald

    Dezelfde checks, getest terwijl elke rij laadt.

  • CHECK constraints with functions Oracle lacks

    niet aangemaakt

    Een check die niet kan worden geschreven, wordt weggelaten en gemeld.

    Rapportregel: check_skipped

  • CHECK constraints added WITH NOCHECK or disabled

    niet aangemaakt

    SQL Server past deze checks niet toe, dus de rijen kunnen ze schenden.

    Rapportregel: check_not_enforced

  • filtered and columnstore indexes, and indexes on CLOB columns

    niet aangemaakt

    IntoSQL schrijft b-tree-indexen op hele kolommen; maak de andere na het laden opnieuw aan.

    Rapportregel: index_skipped

  • foreign keys

    na de data ENABLE NOVALIDATE, daarna gevalideerd met een waarschuwing bij wezen

    De sleutel controleert nieuwe rijen meteen en wordt als laatste gevalideerd; rijen zonder ouder laten hem ongevalideerd met een waarschuwing, in plaats van het laden te stoppen.

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

    weggelaten

    Refererende sleutels in Oracle werken alleen bij verwijderen, met CASCADE of SET NULL.

    Rapportregel: foreign_key_action_unsupported

  • names over 128 bytes

    ingekort

    Namen in Oracle 12.2 en later bevatten 128 bytes; die van SQL Server 128 tekens.

    Rapportregel: name_shortened

  • foreign keys to tables the dump doesn't create

    niet aangemaakt

    Een sleutel kan niet verwijzen naar een tabel die er niet is.

    Rapportregel: foreign_key_skipped

  • tables on a partition scheme

    één tabel met de rijen van elke partitie

    De rijen zijn dezelfde; partitioneer de tabel opnieuw in Oracle als dat nodig is.

    Rapportregel: partitions_dropped

  • temporal tables (SYSTEM_VERSIONING)

    twee tabellen: de huidige rijen en de geschiedenis

    De tabel en zijn geschiedenistabel worden als gewone tabellen gekopieerd; Oracle houdt de geschiedenis niet zelf bij.

    Rapportregel: system_versioning_dropped

  • schemas

    één schema, tabellen met de naam van hun schema ervoor

    Het script laadt in het schema van de gebruiker die het uitvoert, dus tabellen uit verschillende schema's krijgen de naam van hun schema ervoor; tabellen in dbo behouden hun naam.

    Rapportregel: schemas_merged

  • NOT NULL columns with values that become NULL

    NOT NULL weggelaten

    Een kolom waarvan waarden NULL moesten worden, kan NOT NULL niet houden, anders zou het laden stoppen.

    Rapportregel: not_null_relaxed

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

    vermeld in het rapport

    Hun code is geschreven in T-SQL, dus ze worden vermeld zodat je ze opnieuw kunt maken.

    Rapportregel: not_converted_objects

  • scripts without CREATE TABLE (data only)

    typen afgeleid uit de waarden

    Een script met alleen data bevat alleen rijen, dus de typen komen uit de waarden.

    Rapportregel: no_schema

  • expressions in INSERT values

    NULL

    Een converter die geen database draait, kan ze niet evalueren.

    Rapportregel: expression_value

  • types IntoSQL doesn't know

    CLOB

    Tekst kan elke waarde bevatten; wijzig het type na het laden.

    Rapportregel: unknown_type

  • NUL characters in text

    behouden

    VARCHAR2 en CLOB kunnen een NUL-teken bevatten, dus de waarde wordt ongewijzigd gekopieerd.

  • text that isn't valid in its encoding

    de foute bytes als het vervangingsteken

    Het script is UTF-8 en elke waarde moet geldige tekst zijn.

    Rapportregel: invalid_utf8_replaced

  • text decoded twice (ñ)

    ongewijzigd gekopieerd

    Het script bevat precies deze tekens, dus ze worden gekopieerd; het rapport wijst ze aan.

    Rapportregel: mojibake_suspected

In SQL ServerIn OracleRapportregel
bitNUMBER(1) met een CHECK op 0 en 1Oracle 21c heeft geen boolean-kolomtype; 1 en 0 bewaren de waarden op elke versie.
char(n), varchar(n), nchar(n), nvarchar(n)VARCHAR2(n CHAR), in tekens geteldLengtes tellen tekens, zoals nvarchar in SQL Server.
varchar(max), nvarchar(max), text, ntextVARCHAR2(4000 CHAR) als elke waarde in 4000 bytes past, anders CLOBEen VARCHAR2 bevat standaard 4000 bytes en Oracle kan een CLOB niet indexeren, dus tekst blijft VARCHAR2 als de waarden passen en wordt CLOB als ze dat niet doen.text_as_lob
empty strings and empty binary valuesNULLOracle slaat een lege string op als NULL, dus een waarde die ' was, wordt teruggelezen als NULL. Het rapport telt ze per kolom.empty_string_null
decimal(p,s), money, smallmoneyNUMBER(p,s); money als NUMBER(19,4)NUMBER bevat 38 cijfers, net als decimal, dus elke waarde is exact.
datetime, datetime2, smalldatetimeTIMESTAMP(p)Een datetime is een kloktijd, net als TIMESTAMP in Oracle, dat tot negen cijfers van een seconde bewaart. date wordt DATE, dat ook een tijdstip bevat dat op middernacht blijft.
datetimeoffsetTIMESTAMP WITH TIME ZONE, met de offset van elke waardeOracle bewaart offsets van -12:00 tot +14:00; een waarde met een offset voorbij -12:00 wordt in UTC geschreven: hetzelfde moment.
timeINTERVAL DAY TO SECOND vanaf middernachtOracle heeft geen type voor een tijdstip; een interval vanaf middernacht bevat elke waarde.
dates that aren't validNULLEen waarde die geen datum is, wordt NULL en het rapport telt hem.date_out_of_range
json (SQL Server 2025)CLOBDezelfde JSON-waarden, die de JSON-functies van Oracle lezen.
uniqueidentifierVARCHAR2(36)Dezelfde identifiers, in kleine letters geschreven.
binary, varbinary, imageRAW(n) en BLOBBytes blijven bytes.
geometry, geographyBLOB met de eigen bytes van SQL ServerSSMS schrijft ruimtelijke waarden in de serialisatie van SQL Server, die byte voor byte behouden blijft.spatial_as_native
rowversion, timestampBLOB, leegSQL Server stelt een rijversie zelf in en SSMS neemt er geen waarden voor op in het script.rowversion_empty
xml, sql_variant, hierarchyid, vectorVARCHAR2 of CLOB met de tekst van elke waardeOracle heeft geen gelijkwaardig type; xml en sql_variant behouden de tekst van elke waarde en hierarchyid zijn pad, zoals /1/2/.type_replaced
collations that ignore case (_CI_)exacte vergelijkingOracle vergelijkt tekst exact, tenzij anders aangegeven, dus kolommen die in SQL Server hoofdletters negeerden, onderscheiden nu Ana en ana.case_insensitive_collation
IDENTITYGENERATED BY DEFAULT ON NULL AS IDENTITY, verdergaand na het hoogste idDe gekopieerde id's laden ongewijzigd, en de teller gaat verder na het hoogste.
CREATE SEQUENCECREATE SEQUENCE met dezelfde optiesSequences in Oracle werken op dezelfde manier. SSMS legt niet vast hoe ver een sequence is gekomen, dus hij begint waar hij is aangemaakt.
computed columnsvirtuele kolommenOracle berekent gegenereerde kolommen alleen bij het lezen; PERSISTED-kolommen worden virtueel met dezelfde waarden.stored_as_virtual
computed columns with functions Oracle lackseen gewone kolomEen formule die niet kan worden geschreven, levert een gewone kolom en een regel in het rapport op; SSMS neemt geen waarden voor berekende kolommen op in het script.generated_not_translated
defaults with functions Oracle lacks, and NEXT VALUE FORgeen standaardwaardeEen standaardwaarde die niet kan worden geschreven, wordt weggelaten en gemeld.default_not_translated
CHECK constraintsvertaaldDezelfde checks, getest terwijl elke rij laadt.
CHECK constraints with functions Oracle lacksniet aangemaaktEen check die niet kan worden geschreven, wordt weggelaten en gemeld.check_skipped
CHECK constraints added WITH NOCHECK or disabledniet aangemaaktSQL Server past deze checks niet toe, dus de rijen kunnen ze schenden.check_not_enforced
filtered and columnstore indexes, and indexes on CLOB columnsniet aangemaaktIntoSQL schrijft b-tree-indexen op hele kolommen; maak de andere na het laden opnieuw aan.index_skipped
foreign keysna de data ENABLE NOVALIDATE, daarna gevalideerd met een waarschuwing bij wezenDe sleutel controleert nieuwe rijen meteen en wordt als laatste gevalideerd; rijen zonder ouder laten hem ongevalideerd met een waarschuwing, in plaats van het laden te stoppen.
ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULTweggelatenRefererende sleutels in Oracle werken alleen bij verwijderen, met CASCADE of SET NULL.foreign_key_action_unsupported
names over 128 bytesingekortNamen in Oracle 12.2 en later bevatten 128 bytes; die van SQL Server 128 tekens.name_shortened
foreign keys to tables the dump doesn't createniet aangemaaktEen sleutel kan niet verwijzen naar een tabel die er niet is.foreign_key_skipped
tables on a partition schemeéén tabel met de rijen van elke partitieDe rijen zijn dezelfde; partitioneer de tabel opnieuw in Oracle als dat nodig is.partitions_dropped
temporal tables (SYSTEM_VERSIONING)twee tabellen: de huidige rijen en de geschiedenisDe tabel en zijn geschiedenistabel worden als gewone tabellen gekopieerd; Oracle houdt de geschiedenis niet zelf bij.system_versioning_dropped
schemaséén schema, tabellen met de naam van hun schema ervoorHet script laadt in het schema van de gebruiker die het uitvoert, dus tabellen uit verschillende schema's krijgen de naam van hun schema ervoor; tabellen in dbo behouden hun naam.schemas_merged
NOT NULL columns with values that become NULLNOT NULL weggelatenEen kolom waarvan waarden NULL moesten worden, kan NOT NULL niet houden, anders zou het laden stoppen.not_null_relaxed
views, functions, procedures, triggers, synonyms, types and partition functionsvermeld in het rapportHun code is geschreven in T-SQL, dus ze worden vermeld zodat je ze opnieuw kunt maken.not_converted_objects
scripts without CREATE TABLE (data only)typen afgeleid uit de waardenEen script met alleen data bevat alleen rijen, dus de typen komen uit de waarden.no_schema
expressions in INSERT valuesNULLEen converter die geen database draait, kan ze niet evalueren.expression_value
types IntoSQL doesn't knowCLOBTekst kan elke waarde bevatten; wijzig het type na het laden.unknown_type
NUL characters in textbehoudenVARCHAR2 en CLOB kunnen een NUL-teken bevatten, dus de waarde wordt ongewijzigd gekopieerd.
text that isn't valid in its encodingde foute bytes als het vervangingstekenHet script is UTF-8 en elke waarde moet geldige tekst zijn.invalid_utf8_replaced
text decoded twice (ñ)ongewijzigd gekopieerdHet script bevat precies deze tekens, dus ze worden gekopieerd; het rapport wijst ze aan.mojibake_suspected

Het script in Oracle laden

Het script maakt de tabellen aan, kopieert de rijen en voegt daarna sleutels, indexen en refererende sleutels toe, zodat het snel laadt en bij de eerste fout stopt.

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

Refererende sleutels worden toegevoegd met ENABLE NOVALIDATE, zodat nieuwe rijen meteen worden gecontroleerd, en daarna gevalideerd. Verwijst een oude rij naar een rij die niet bestaat, dan vertelt het script welke constraint het is en laat het die ongevalideerd, in plaats van halverwege te mislukken.

Voer bij een grote dump SQL*Plus uit op dezelfde machine als de database. Het script commit elke 100 rijen. De gebruiker die het uitvoert, heeft CREATE TABLE, CREATE SEQUENCE, CREATE TRIGGER en CREATE PROCEDURE nodig, en quota op zijn tablespace.

Een dump van SQL Server maken voor het beste resultaat

De converter leest wat de dump bevat. Met deze opties blijft er meer van je data in staan:

  • Klik in SSMS met rechts op de database, kies Tasks, Generate Scripts en selecteer de tabellen. dbatools, mssql-scripter en andere tools op basis van dezelfde bibliotheek schrijven hetzelfde script.
  • Zet onder Advanced Types of data to script op Schema and data. Een script van alleen het schema bevat tabellen zonder rijen.
  • Sla het op als Unicode, de standaard van SSMS, of als UTF-8: beide worden op dezelfde manier gelezen, en gzip werkt ook.

Wat niet wordt geconverteerd

Weergaven, functies, procedures, triggers, synoniemen, regels en beveiligingsbeleid zijn geschreven in T-SQL. Ze staan op naam in het rapport en worden nooit stilletjes weggelaten, zodat je ze kunt herschrijven voor Oracle.

Vragen over SQL Server naar Oracle

Staat je vraag er niet bij? Schrijf ons via de contactpagina en een mens antwoordt. Contactpagina

Wordt mijn dump geüpload?

Nee. De converter draait in je browser en leest de dump in delen van je schijf, dus hij verlaat je computer nooit. De desktopapp en de opdrachtregel converteren ook op je computer.

Hoe groot mag de dump zijn?

De converter houdt nooit de hele dump in het geheugen: hij leest het bestand twee keer, in bereiken, en schrijft het script gaandeweg. Dumps van meerdere gigabytes worden geconverteerd in de browser, in de desktopapp en met de opdrachtregel.

Leest het het UTF-16-bestand dat SSMS opslaat?

Ja. SSMS slaat scripts standaard op als UTF-16, en de converter leest UTF-16 en UTF-8 even goed, met of zonder gzip, met GO tussen batches.

Van welke SQL Server-versies kan het script komen?

Scripts die SSMS, dbatools of mssql-scripter schrijven vanaf SQL Server 2017. Elk testscript komt van SQL Server 2017, 2022 en 2025 en wordt cel voor cel met zijn bron vergeleken.

Blijven IDENTITY-waarden behouden?

Ja. IDENTITY-kolommen worden identity-kolommen, elke rij behoudt zijn id en het volgende id gaat verder na het hoogste. Sequences worden aangemaakt met dezelfde opties.

Wat gebeurt er met money, datetimeoffset en andere SQL Server-typen?

bit wordt NUMBER(1), datetime2 TIMESTAMP met elk cijfer, datetimeoffset TIMESTAMP WITH TIME ZONE met zijn offset, en nvarchar(max) CLOB als de waarden niet in een VARCHAR2 passen. Lege strings worden NULL, zoals Oracle ze opslaat, en het rapport telt ze.

En procedures, triggers en weergaven?

Ze staan op naam in het rapport en worden niet geconverteerd, omdat elke database ze in een eigen taal schrijft.

Op welke Oracle-versies laadt het script?

Oracle 19c en later. Elk testscript laadt op 21c en 23ai en stopt bij de eerste fout als er iets misgaat.