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.
18 rijen geconverteerd, 2 correcties, geen afgewezen
Tabellen in shop_2024_sqlserver.sqlSQL Server-dump · geschreven door SQL Server Management Objects · utf-8
ordersgeschreven als ORDERS10 rijen1
11 kolommen ID NUMBER(10) not null CUSTOMER_ID NUMBER(10) not null STATUS VARCHAR2(10 CHAR) not null TOTAL NUMBER(19,4) not null ITEMS NUMBER(3) 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) customersgeschreven als CUSTOMERS8 rijen1
8 kolommen ID NUMBER(10) not null NAME VARCHAR2(100 CHAR) not null EMAIL VARCHAR2(200 CHAR) not null COUNTRY VARCHAR2(2 CHAR) not null IS_ACTIVE NUMBER(1) not null SIGNED_UP DATE CREATED_AT TIMESTAMP(0) WITH TIME ZONE not null ROW_VERSION RAW(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
- "total_with_tax" van orders wordt in de bron opgeslagen; Oracle berekent het bij het lezen.
- "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 Server | In Oracle | Rapportregel |
|---|---|---|
| bit | NUMBER(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, ntext | VARCHAR2(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 values | NULLOracle 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, 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 waardeOracle 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 middernachtOracle heeft geen type voor een tijdstip; een interval vanaf middernacht bevat elke waarde. | |
| dates that aren't valid | NULLEen 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. | |
| uniqueidentifier | VARCHAR2(36)Dezelfde identifiers, in kleine letters geschreven. | |
| binary, varbinary, image | RAW(n) en BLOBBytes blijven bytes. | |
| geometry, geography | BLOB 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, timestamp | BLOB, leegSQL Server stelt een rijversie zelf in en SSMS neemt er geen waarden voor op in het script. | rowversion_empty |
| xml, sql_variant, hierarchyid, vector | VARCHAR2 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 |
| IDENTITY | GENERATED 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 SEQUENCE | CREATE 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 columns | virtuele kolommenOracle berekent gegenereerde kolommen alleen bij het lezen; PERSISTED-kolommen worden virtueel met dezelfde waarden. | stored_as_virtual |
| computed columns with functions Oracle lacks | een 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 FOR | geen standaardwaardeEen standaardwaarde die niet kan worden geschreven, wordt weggelaten en gemeld. | default_not_translated |
| CHECK constraints | vertaaldDezelfde checks, getest terwijl elke rij laadt. | |
| CHECK constraints with functions Oracle lacks | niet aangemaaktEen check die niet kan worden geschreven, wordt weggelaten en gemeld. | check_skipped |
| CHECK constraints added WITH NOCHECK or disabled | niet aangemaaktSQL Server past deze checks niet toe, dus de rijen kunnen ze schenden. | check_not_enforced |
| filtered and columnstore indexes, and indexes on CLOB columns | niet aangemaaktIntoSQL schrijft b-tree-indexen op hele kolommen; maak de andere na het laden opnieuw aan. | index_skipped |
| foreign keys | na 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 DEFAULT | weggelatenRefererende sleutels in Oracle werken alleen bij verwijderen, met CASCADE of SET NULL. | foreign_key_action_unsupported |
| names over 128 bytes | ingekortNamen 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 create | niet 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 NULL | NOT 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 functions | vermeld 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 values | NULLEen converter die geen database draait, kan ze niet evalueren. | expression_value |
| types IntoSQL doesn't know | CLOBTekst kan elke waarde bevatten; wijzig het type na het laden. | unknown_type |
| NUL characters in text | behoudenVARCHAR2 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 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.sqlRefererende 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.