---
title: "Oracle to SQL Server data types"
description: "Every Oracle data type that SQL Server stores differently, what the converter writes for it, when, and the report line."
canonical: https://intosql.com/docs/types/oracle-to-sql-server
last_updated: 2026-10-15
---

# Oracle to SQL Server data types

Each row is a type from Oracle that SQL Server stores differently: what the SQL Server script gets, why, and the line the report writes about it. The rows come from the converter's own rules, so this page matches what it does.

**Convert in the browser:** [Oracle to SQL Server](/oracle-to-sql-server) opens the converter set up for this pair. The [Oracle to SQL Server migration guide](/docs/migrations/oracle-to-sql-server) covers dumping, loading and the rules for keys, indexes and names.

A report line is a fix when the converter changed something and lists it, or a problem when a value or object is worth a look.

## Numbers

| In Oracle | In SQL Server | Why | Report line |
| --- | --- | --- | --- |
| 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. | None |

## Booleans and bits

| In Oracle | In SQL Server | Why | Report line |
| --- | --- | --- | --- |
| BOOLEAN (23ai) | bit | SQL Server has no boolean column, so TRUE and FALSE are 1 and 0. | None |

## Text

| In Oracle | In SQL Server | Why | Report line |
| --- | --- | --- | --- |
| 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. | None |
| 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. | `text_length_widened` (fix) |
| NUL characters in text | kept | nvarchar can hold a NUL character, so the value is copied as it is. | None |
| 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. | `invalid_utf8_replaced` (problem) |

## Dates and times

| In Oracle | In SQL Server | Why | Report line |
| --- | --- | --- | --- |
| 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. | `type_replaced` (fix) |
| 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. | None |
| TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH LOCAL TIME ZONE | datetimeoffset, with each value's offset | The same type and values. | None |
| 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. | `date_out_of_range` (problem) |

## Binary

| In Oracle | In SQL Server | Why | Report line |
| --- | --- | --- | --- |
| BLOB, RAW(n), LONG RAW | binary(n), varbinary(n) and varbinary(max) | Bytes stay bytes. | None |

## JSON, spatial and other types

| In Oracle | In SQL Server | Why | Report line |
| --- | --- | --- | --- |
| JSON (21c), and CLOB holding JSON | nvarchar(max) | The same JSON values; a SQL NULL the export wrote as 'null' stays NULL. | None |
| 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. | None |
| types IntoSQL doesn't know, and object types | nvarchar(max) | Text holds any value; change the type after loading. | `unknown_type` (problem) |
| 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. | `invalid_value_null` (problem) |

## Counters and identities

| In Oracle | In SQL Server | Why | Report line |
| --- | --- | --- | --- |
| 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. | None |
| 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. | `counter_dropped` (problem) |

## Other pairs

- Oracle into [PostgreSQL](/docs/types/oracle-to-postgresql), [MySQL](/docs/types/oracle-to-mysql), [MariaDB](/docs/types/oracle-to-mariadb), [SQLite](/docs/types/oracle-to-sqlite), [Oracle](/docs/types/oracle-to-oracle)
- Into SQL Server from [MySQL](/docs/types/mysql-to-sql-server), [MariaDB](/docs/types/mariadb-to-sql-server), [PostgreSQL](/docs/types/postgresql-to-sql-server), [SQL Server](/docs/types/sql-server-to-sql-server), [SQLite](/docs/types/sqlite-to-sql-server)
- [Every pair](/docs/types#from-one-database-to-another)
