Skip to content
IntoSQL home

Convert Oracle to SQL Server

Drop the .sql file SQL Developer's Database Export or SQLcl writes, with its tables and Insert statements, and download a script for SQL Server with the same tables, keys, indexes and data. Every value SQL Server can't hold as it is, and every object it doesn't carry, is listed in the report.

Your file
sqlshop_2024_oracle.sqlSample file, 9.3 kB
Your database

18 rows converted, 2 fixes, none rejected

Show

Tables in shop_2024_oracle.sqlOracle dump · written by SQL Developer · utf-8

  • customers8 rows1
    7 columns
    idbigint not null
    namenvarchar(200) not null
    emailnvarchar(150) not null
    countrynvarchar(2) not null
    is_activesmallint not null
    signed_updatetime2(0)
    created_atdatetime2(0) not null
  • orders10 rows1
    9 columns
    idbigint not null
    customer_idbigint not null
    invoicebigint
    statusnvarchar(10) not null
    totaldecimal(10,2) not null
    itemsint not null
    ordered_atdatetime2(0) not null
    shipped_atdatetime2(0)
    notenvarchar(510)
-- Written by IntoSQL from a Oracle dump. Load it with: sqlcmd -b -f 65001 -d <database> -i <file>
SET NOCOUNT ON;
SET ANSI_NULLS ON;
SET QUOTED_IDENTIFIER ON;
SET ANSI_PADDING ON;
SET ANSI_WARNINGS ON;
SET ARITHABORT ON;
SET CONCAT_NULL_YIELDS_NULL ON;
SET NUMERIC_ROUNDABORT OFF;
GO

CREATE SEQUENCE [dbo].[invoice_numbers] AS bigint START WITH 1020 INCREMENT BY 1 MINVALUE 1;
GO
CREATE TABLE [dbo].[customers] (
    [id] bigint IDENTITY(1, 1) NOT NULL,
    [name] nvarchar(200) COLLATE Latin1_General_100_BIN2 NOT NULL,
    [email] nvarchar(150) COLLATE Latin1_General_100_BIN2 NOT NULL,
    [country] nvarchar(2) COLLATE Latin1_General_100_BIN2 DEFAULT N'US' NOT NULL,
    [is_active] smallint DEFAULT 1 NOT NULL,
    [signed_up] datetime2(0) NULL,
    [created_at] datetime2(0) DEFAULT SYSDATETIME() NOT NULL,
    CONSTRAINT [check1] CHECK ([is_active] IN (0, 1)),
    CONSTRAINT [PK_customers] PRIMARY KEY ([id])
);
GO

CREATE TABLE [dbo].[orders] (
    [id] bigint IDENTITY(1, 1) NOT NULL,
    [customer_id] bigint NOT NULL,
    [invoice] bigint DEFAULT (NEXT VALUE FOR [dbo].[invoice_numbers]) NULL,
    [status] nvarchar(10) COLLATE Latin1_General_100_BIN2 DEFAULT N'pending' NOT NULL,
    [total] decimal(10,2) NOT NULL,
    [items] int DEFAULT 1 NOT NULL,
    [ordered_at] datetime2(0) NOT NULL,
    [shipped_at] datetime2(0) NULL,
    [note] nvarchar(510) COLLATE Latin1_General_100_BIN2 NULL,
    CONSTRAINT [check1_2] CHECK ([status] IN (N'pending', N'paid', N'shipped', N'cancelled')),
    CONSTRAINT [PK_orders] PRIMARY KEY ([id])
);
GO

SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [signed_up], [created_at]) VALUES
(1,N'Ana Martínez',N'ana@example.com',N'MX',1,'2023-01-15 00:00:00','2023-01-15 10:24:00.0000000');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [signed_up], [created_at]) VALUES
(2,N'Zoë Müller',N'zoe@example.de',N'DE',1,'2023-02-03 00:00:00','2023-02-03 08:11:42.0000000');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [signed_up], [created_at]) VALUES
(3,N'José Peña',N'jose@example.es',N'ES',0,'2023-03-21 00:00:00','2023-03-21 19:05:17.0000000');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [signed_up], [created_at]) VALUES
(4,N'李雷',N'lilei@example.cn',N'CN',1,'2023-05-09 00:00:00','2023-05-09 02:40:00.0000000');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [signed_up], [created_at]) VALUES
(5,N'Noah O''Brien',N'noah@example.ie',N'IE',1,NULL,'2023-06-30 14:00:00.0000000');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [signed_up], [created_at]) VALUES
(6,N'Amélie Laurent',N'amelie@example.fr',N'FR',1,'2024-01-02 00:00:00','2024-01-02 09:30:00.0000000');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [signed_up], [created_at]) VALUES
(7,N'Ravi Patel',N'ravi@example.in',N'IN',0,'2024-02-29 00:00:00','2024-02-29 23:59:59.0000000');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[customers] ON;
INSERT INTO [dbo].[customers] ([id], [name], [email], [country], [is_active], [signed_up], [created_at]) VALUES
(8,N'Sofia Rossi 🌻',N'sofia@example.it',N'IT',1,'2024-04-12 00:00:00','2024-04-12 12:12:12.0000000');
SET IDENTITY_INSERT [dbo].[customers] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(1,1,1000,N'shipped',129.9,3,'2024-03-01 10:00:00','2024-03-02 16:30:00',NULL);
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(2,2,1001,N'paid',54,1,'2024-03-02 11:15:00',NULL,N'Gift wrap 🎁');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(3,1,1002,N'cancelled',12.5,1,'2024-03-03 09:45:00',NULL,N'Customer changed their mind');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(4,4,1003,N'shipped',980,12,'2024-03-05 02:10:00','2024-03-07 08:00:00',N'请小心轻放');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(5,5,1004,N'pending',45.75,2,'2024-03-08 17:20:00',NULL,N'Leave at the door; ring twice');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(6,6,1005,N'shipped',310.4,5,'2024-03-10 13:00:00','2024-03-11 09:00:00',N'Fragile: "glass"');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(7,8,1006,N'paid',76.2,2,'2024-03-11 18:45:00',NULL,NULL);
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(8,2,1007,N'paid',19.99,1,'2024-03-12 08:00:00',NULL,N'Paid at the counter');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(9,3,1008,N'shipped',64,2,'2024-03-14 15:30:00',NULL,N'Shipping date never recorded');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO
SET IDENTITY_INSERT [dbo].[orders] ON;
INSERT INTO [dbo].[orders] ([id], [customer_id], [invoice], [status], [total], [items], [ordered_at], [shipped_at], [note]) VALUES
(10,7,1009,N'paid',1499,1,'2024-03-15 21:05:00',NULL,N'C:\Users\ravi\invoice.pdf');
SET IDENTITY_INSERT [dbo].[orders] OFF;
GO

-- Indexes, foreign keys, counters and triggers, after the rows.
CREATE UNIQUE INDEX [customers_email_uk] ON [dbo].[customers] ([email]);
CREATE INDEX [orders_status_date_ix] ON [dbo].[orders] ([status], [ordered_at]);
ALTER TABLE [dbo].[orders] WITH NOCHECK ADD CONSTRAINT [orders_customer_fk] FOREIGN KEY ([customer_id]) REFERENCES [dbo].[customers] ([id]);
BEGIN TRY ALTER TABLE [dbo].[orders] WITH CHECK CHECK CONSTRAINT [orders_customer_fk]; END TRY BEGIN CATCH PRINT N'Foreign key ' + N'[orders_customer_fk]' + N' has rows without a parent: it stays unchecked, and new rows are checked.'; END CATCH;
DECLARE @next decimal(38,0) = (SELECT MAX([id]) FROM [dbo].[customers]); IF @next IS NOT NULL BEGIN IF @next < 0 SET @next = 0; DBCC CHECKIDENT (N'[dbo].[customers]', RESEED, @next) WITH NO_INFOMSGS; END;
GO
EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = N'People who bought at least once', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'customers';
DECLARE @next decimal(38,0) = (SELECT MAX([id]) FROM [dbo].[orders]); IF @next IS NOT NULL BEGIN IF @next < 0 SET @next = 0; DBCC CHECKIDENT (N'[dbo].[orders]', RESEED, @next) WITH NO_INFOMSGS; END;
GO
GO

Fixes

  1. "name" of customers holds characters SQL Server counts twice, such as emoji, so it is nvarchar(200).
  2. "note" of orders holds characters SQL Server counts twice, such as emoji, so it is nvarchar(510).

Your file is converted on this computer and never uploaded.

Other samples:

What changes from Oracle to SQL Server

Each row is a rule the converter applies, with the report line it writes when the rule changes something in your data.

  • BOOLEAN (23ai)

    bit

    SQL Server has no boolean column, so TRUE and FALSE are 1 and 0.

  • VARCHAR2(n BYTE|CHAR), NVARCHAR2(n), CHAR(n), NCHAR(n), CLOB, NCLOB, LONG

    nvarchar(n), nchar(n) and nvarchar(max)

    Lengths count characters, whether Oracle counted bytes or characters, so every value fits.

  • VARCHAR2 and NVARCHAR2 past what the target's own types hold

    nvarchar(2n), or nvarchar(max) past 4000

    nvarchar counts UTF-16 units and an emoji takes two, so the column gets room for every value.

    Report line: text_length_widened

  • NUMBER, NUMBER(p,s), FLOAT(b)

    decimal(p,s), or bigint

    NUMBER keeps every digit; a NUMBER without precision whose values are all whole numbers of up to 18 digits is a 64-bit integer, and a negative scale holds as many digits before the point.

  • INTERVAL YEAR TO MONTH, INTERVAL DAY TO SECOND

    nvarchar(100) with Oracle's text, such as +01-06

    SQL Server has no interval type; the text keeps every part.

    Report line: type_replaced

  • DATE, TIMESTAMP(p)

    datetime2(p)

    Oracle's DATE holds a time to the second, so it is a date and time. An export in an American or German session writes dates without their time or century (DD-MON-RR); export in an ISO session (SYYYY-MM-DD HH24:MI:SS) to keep them.

  • TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH LOCAL TIME ZONE

    datetimeoffset, with each value's offset

    The same type and values.

  • JSON (21c), and CLOB holding JSON

    nvarchar(max)

    The same JSON values; a SQL NULL the export wrote as 'null' stays NULL.

  • BLOB, RAW(n), LONG RAW

    binary(n), varbinary(n) and varbinary(max)

    Bytes stay bytes.

  • ROWID, UROWID, XMLTYPE, SDO_GEOMETRY

    nvarchar(max), and xml for XMLTYPE

    Oracle's own types have no equivalent; their values keep their text, ROWID values included, though they mean nothing off Oracle.

  • collations that ignore case (BINARY_CI)

    the same collation on each column

    Columns compare and sort as they did, and unique keys keep the same rows apart.

  • identity columns, and a sequence a BEFORE INSERT trigger assigns

    IDENTITY, continuing after the highest id

    The copied ids load as they are, and the counter continues after the highest one. A column a trigger fills from a sequence (the way before 12c) is an identity too.

  • identity columns the target can't count

    a plain integer

    SQL Server counts one IDENTITY column per table; any other keeps its values without a counter.

    Report line: counter_dropped

  • CREATE SEQUENCE

    CREATE SEQUENCE with the same options

    The export writes where a sequence has reached as its START WITH, so it continues from there.

  • virtual columns (GENERATED ALWAYS AS ... VIRTUAL)

    computed columns

    SQL Server computes them from the same formula; the values the export wrote for them are left out.

  • virtual columns with functions IntoSQL doesn't write, and the || operator

    a plain column

    A formula that can't be written for SQL Server leaves a plain column and a report line; the values the export wrote for virtual columns are left out, and SQL Server has none to compute.

    Report line: generated_not_translated

  • defaults with functions IntoSQL doesn't write (SYS_GUID(), ||)

    no default

    A default that can't be written is left out and reported.

    Report line: default_not_translated

  • CHECK constraints

    translated

    The same checks, tested as each row loads.

  • CHECK constraints with functions IntoSQL doesn't write

    not created

    A check that can't be written is left out and reported.

    Report line: check_skipped

  • CHECK constraints that are DISABLE or ENABLE NOVALIDATE

    not created

    Oracle doesn't apply these checks to the rows already there, so the rows may break them.

    Report line: check_not_enforced

  • function-based, bitmap and domain indexes

    not created

    IntoSQL writes b-tree indexes on whole columns; create the others again after loading.

    Report line: index_skipped

  • foreign keys

    after the data WITH NOCHECK, then checked with a warning on orphans

    The key is created after the rows and checked last; rows without a parent leave it unchecked with a warning instead of stopping the load.

  • ON DELETE CASCADE that cascades in a cycle or along a second path

    NO ACTION

    SQL Server refuses cascades that loop or take a second path, so the key is created without that action and the report names it.

    Report line: foreign_key_action_dropped

  • foreign keys to tables the export doesn't create, and DISABLE or NOVALIDATE ones

    not created

    A key can't name a table that isn't there, and one Oracle doesn't check may have rows without a parent.

    Report line: foreign_key_skipped

  • partitioned tables

    one table with every partition's rows

    The rows are the same; partition the table again in SQL Server if it needs it.

    Report line: partitions_dropped

  • NOT NULL columns with values that become NULL

    NOT NULL dropped

    A column whose values had to become NULL can't keep NOT NULL, or the load would stop.

    Report line: not_null_relaxed

  • views, synonyms, types, packages, procedures, functions and other triggers

    listed in the report

    Their code is written in PL/SQL, so they are listed for you to recreate.

    Report line: not_converted_objects

  • exports without CREATE TABLE (data only)

    types read from the values

    A data-only export has only rows, so the types come from the values.

    Report line: no_schema

  • expressions in INSERT values other than the ones exports write

    NULL

    A converter that doesn't run a database can't evaluate them; to_date, to_timestamp, TO_CLOB, HEXTORAW and the others exports write are read.

    Report line: expression_value

  • types IntoSQL doesn't know, and object types

    nvarchar(max)

    Text holds any value; change the type after loading.

    Report line: unknown_type

  • dates before year 1 and time zones given as region names

    NULL

    A value that isn't a date becomes NULL and the report counts it.

    Report line: date_out_of_range

  • NaN and Infinity in BINARY_FLOAT and BINARY_DOUBLE

    NULL

    SQL Server's floating-point types have no NaN or infinity, so those values become NULL and the report counts them.

    Report line: invalid_value_null

  • NUL characters in text

    kept

    nvarchar can hold a NUL character, so the value is copied as it is.

  • text that isn't valid in its encoding

    the bad bytes as the replacement character

    The script is UTF-8 and every value has to be valid text.

    Report line: invalid_utf8_replaced

  • text decoded twice (ñ)

    copied as it is

    The script holds exactly these characters, so they are copied; the report points them out.

    Report line: mojibake_suspected

In OracleIn SQL ServerReport line
BOOLEAN (23ai)bitSQL Server has no boolean column, so TRUE and FALSE are 1 and 0.
VARCHAR2(n BYTE|CHAR), NVARCHAR2(n), CHAR(n), NCHAR(n), CLOB, NCLOB, LONGnvarchar(n), nchar(n) and nvarchar(max)Lengths count characters, whether Oracle counted bytes or characters, so every value fits.
VARCHAR2 and NVARCHAR2 past what the target's own types holdnvarchar(2n), or nvarchar(max) past 4000nvarchar counts UTF-16 units and an emoji takes two, so the column gets room for every value.text_length_widened
NUMBER, NUMBER(p,s), FLOAT(b)decimal(p,s), or bigintNUMBER keeps every digit; a NUMBER without precision whose values are all whole numbers of up to 18 digits is a 64-bit integer, and a negative scale holds as many digits before the point.
INTERVAL YEAR TO MONTH, INTERVAL DAY TO SECONDnvarchar(100) with Oracle's text, such as +01-06SQL Server has no interval type; the text keeps every part.type_replaced
DATE, TIMESTAMP(p)datetime2(p)Oracle's DATE holds a time to the second, so it is a date and time. An export in an American or German session writes dates without their time or century (DD-MON-RR); export in an ISO session (SYYYY-MM-DD HH24:MI:SS) to keep them.
TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH LOCAL TIME ZONEdatetimeoffset, with each value's offsetThe same type and values.
JSON (21c), and CLOB holding JSONnvarchar(max)The same JSON values; a SQL NULL the export wrote as 'null' stays NULL.
BLOB, RAW(n), LONG RAWbinary(n), varbinary(n) and varbinary(max)Bytes stay bytes.
ROWID, UROWID, XMLTYPE, SDO_GEOMETRYnvarchar(max), and xml for XMLTYPEOracle's own types have no equivalent; their values keep their text, ROWID values included, though they mean nothing off Oracle.
collations that ignore case (BINARY_CI)the same collation on each columnColumns compare and sort as they did, and unique keys keep the same rows apart.
identity columns, and a sequence a BEFORE INSERT trigger assignsIDENTITY, continuing after the highest idThe copied ids load as they are, and the counter continues after the highest one. A column a trigger fills from a sequence (the way before 12c) is an identity too.
identity columns the target can't counta plain integerSQL Server counts one IDENTITY column per table; any other keeps its values without a counter.counter_dropped
CREATE SEQUENCECREATE SEQUENCE with the same optionsThe export writes where a sequence has reached as its START WITH, so it continues from there.
virtual columns (GENERATED ALWAYS AS ... VIRTUAL)computed columnsSQL Server computes them from the same formula; the values the export wrote for them are left out.
virtual columns with functions IntoSQL doesn't write, and the || operatora plain columnA formula that can't be written for SQL Server leaves a plain column and a report line; the values the export wrote for virtual columns are left out, and SQL Server has none to compute.generated_not_translated
defaults with functions IntoSQL doesn't write (SYS_GUID(), ||)no defaultA default that can't be written is left out and reported.default_not_translated
CHECK constraintstranslatedThe same checks, tested as each row loads.
CHECK constraints with functions IntoSQL doesn't writenot createdA check that can't be written is left out and reported.check_skipped
CHECK constraints that are DISABLE or ENABLE NOVALIDATEnot createdOracle doesn't apply these checks to the rows already there, so the rows may break them.check_not_enforced
function-based, bitmap and domain indexesnot createdIntoSQL writes b-tree indexes on whole columns; create the others again after loading.index_skipped
foreign keysafter the data WITH NOCHECK, then checked with a warning on orphansThe key is created after the rows and checked last; rows without a parent leave it unchecked with a warning instead of stopping the load.
ON DELETE CASCADE that cascades in a cycle or along a second pathNO ACTIONSQL Server refuses cascades that loop or take a second path, so the key is created without that action and the report names it.foreign_key_action_dropped
foreign keys to tables the export doesn't create, and DISABLE or NOVALIDATE onesnot createdA key can't name a table that isn't there, and one Oracle doesn't check may have rows without a parent.foreign_key_skipped
partitioned tablesone table with every partition's rowsThe rows are the same; partition the table again in SQL Server if it needs it.partitions_dropped
NOT NULL columns with values that become NULLNOT NULL droppedA column whose values had to become NULL can't keep NOT NULL, or the load would stop.not_null_relaxed
views, synonyms, types, packages, procedures, functions and other triggerslisted in the reportTheir code is written in PL/SQL, so they are listed for you to recreate.not_converted_objects
exports without CREATE TABLE (data only)types read from the valuesA data-only export has only rows, so the types come from the values.no_schema
expressions in INSERT values other than the ones exports writeNULLA converter that doesn't run a database can't evaluate them; to_date, to_timestamp, TO_CLOB, HEXTORAW and the others exports write are read.expression_value
types IntoSQL doesn't know, and object typesnvarchar(max)Text holds any value; change the type after loading.unknown_type
dates before year 1 and time zones given as region namesNULLA value that isn't a date becomes NULL and the report counts it.date_out_of_range
NaN and Infinity in BINARY_FLOAT and BINARY_DOUBLENULLSQL Server's floating-point types have no NaN or infinity, so those values become NULL and the report counts them.invalid_value_null
NUL characters in textkeptnvarchar can hold a NUL character, so the value is copied as it is.
text that isn't valid in its encodingthe bad bytes as the replacement characterThe script is UTF-8 and every value has to be valid text.invalid_utf8_replaced
text decoded twice (ñ)copied as it isThe script holds exactly these characters, so they are copied; the report points them out.mojibake_suspected

Load the script into SQL Server

The script creates the tables, copies the rows, then adds keys, indexes and foreign keys, so it loads fast and stops at the first error.

sqlcmd -b -f 65001 -S localhost -d mydb -i oracle.sql_server.sql

Foreign keys are added WITH NOCHECK and then checked. If a row points to a row that doesn't exist, the script says which constraint and leaves it unchecked, instead of failing half way.

For a large dump, run sqlcmd on the same machine as the server. Each batch of up to 1000 rows commits on its own, so the transaction log stays small.

Dump Oracle for the best result

The converter reads what the dump holds. These options keep more of your data in it:

  • In SQL Developer, choose Tools, Database Export, with DDL and the Insert data format. SQLcl writes the same with SET SQLFORMAT INSERT.
  • Run ALTER SESSION SET NLS_DATE_FORMAT = 'SYYYY-MM-DD HH24:MI:SS' before exporting: the default format writes dates without their time or century.
  • A .dmp file from exp or expdp is binary: import it into an Oracle database, Oracle Database Free in Docker for one, and export it with SQL Developer.

What isn't converted

Views, packages, procedures, functions, triggers, types and synonyms are written in PL/SQL. They are listed in the report by name, never dropped silently, so you can rewrite them for SQL Server.

Questions about Oracle to SQL Server

Not answered here? Write to us from the contact page and a person replies. Contact page

Is my dump uploaded?

No. The converter runs in your browser and reads the dump from your disk in pieces, so it never leaves your computer. The desktop app and the command line convert on your computer too.

How large can the dump be?

The converter never holds the whole dump in memory: it reads the file twice, by ranges, and writes the script as it goes. Multi-gigabyte dumps convert in the browser, in the desktop app and with the command line.

Can I convert a .dmp file from exp or expdp?

Not directly: Data Pump and the original Export write a binary format only Oracle reads. Import it into any Oracle database, Oracle Database Free runs in Docker, and export it with SQL Developer's Database Export or SQLcl. The converter says so when it gets a .dmp file.

Which Oracle versions can the export come from?

Exports from SQL Developer and SQLcl, with DBMS_METADATA's table definitions, from Oracle 11g on. Every test export comes from Oracle 21c and 23ai, in American, German and ISO sessions, and is compared with its source cell by cell.

What happens to NUMBER, DATE and the other Oracle types?

NUMBER becomes decimal, or bigint for whole numbers; DATE becomes datetime2(0), keeping its time; text nvarchar, compared exactly as in Oracle; CLOB nvarchar(max), BLOB varbinary(max). NaN and Infinity become NULL and the report counts them.

Are identity columns and sequences kept?

Yes. Identity columns become IDENTITY columns and continue after the highest id; sequences become SQL Server sequences, and defaults that draw from one keep drawing from it.

What about PL/SQL packages, procedures and triggers?

They are listed in the report by name and not converted, because each database writes them in its own language.

Which SQL Server versions does the script load on?

SQL Server 2017 to 2025. The same script loads on each of them, stopping at the first error if anything goes wrong.