---
title: "Oracle data types between versions"
description: "Every Oracle data type an older or newer Oracle stores differently, what the converter writes for it, and the report line."
canonical: https://intosql.com/docs/types/oracle-to-oracle
last_updated: 2026-10-15
---

# Oracle data types between versions

Each row is a type from Oracle that an older or newer Oracle stores differently: what the 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 Oracle](/oracle-to-oracle) opens the converter set up for this pair. The [Oracle to Oracle migration guide](/docs/migrations/oracle-to-oracle) 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 the dump | In the script | Why | Report line |
| --- | --- | --- | --- |
| NUMBER, NUMBER(p,s), FLOAT(b) | the same NUMBER types | The same NUMBER and FLOAT types, with every digit. | None |

## Booleans and bits

| In the dump | In the script | Why | Report line |
| --- | --- | --- | --- |
| BOOLEAN (23ai) | BOOLEAN on 23ai, else NUMBER(1) with a CHECK of 0 and 1 | TRUE and FALSE stay true and false. | None |

## Text

| In the dump | In the script | Why | Report line |
| --- | --- | --- | --- |
| VARCHAR2(n BYTE\|CHAR), NVARCHAR2(n), CHAR(n), NCHAR(n), CLOB, NCLOB, LONG | the same types, with their BYTE or CHAR lengths | The same text types; LONG becomes CLOB, which every version since 8 prefers. | None |
| VARCHAR2 and NVARCHAR2 past what the target's own types hold | VARCHAR2(4000 CHAR) when every value fits 4000 bytes, else CLOB | A VARCHAR2 holds 4000 bytes by default and Oracle can't index a CLOB, so text keeps VARCHAR2 when its values fit and is a CLOB when they don't. | `text_as_lob` (fix) |
| NUL characters in text | kept | VARCHAR2 and CLOB 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 the dump | In the script | Why | Report line |
| --- | --- | --- | --- |
| INTERVAL YEAR TO MONTH, INTERVAL DAY TO SECOND | the same INTERVAL types | The same intervals. | None |
| DATE, TIMESTAMP(p) | DATE and TIMESTAMP(p), as declared | The same types, so every date keeps its time to the second. | None |
| TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH LOCAL TIME ZONE | the same types | Oracle keeps the offsets from -12:00 to +14:00; a value with an offset beyond -12:00 is written in UTC, the same instant. | 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 the dump | In the script | Why | Report line |
| --- | --- | --- | --- |
| BLOB, RAW(n), LONG RAW | the same types; LONG RAW as BLOB | Bytes stay bytes. | None |

## JSON, spatial and other types

| In the dump | In the script | Why | Report line |
| --- | --- | --- | --- |
| JSON (21c), and CLOB holding JSON | JSON on 21c and later, else CLOB | The same JSON values; a SQL NULL the export wrote as 'null' stays NULL. | None |
| ROWID, UROWID, XMLTYPE, SDO_GEOMETRY | CLOB with their text | XMLTYPE, ROWID and UROWID keep their text in a CLOB, so the script loads on every version from 19c. | `type_replaced` (fix) |
| types IntoSQL doesn't know, and object types | CLOB | Text holds any value; change the type after loading. | `unknown_type` (problem) |
| NaN and Infinity in BINARY_FLOAT and BINARY_DOUBLE | NaN and Infinity kept | Oracle's floating-point types hold NaN and infinity. | None |

## Counters and identities

| In the dump | In the script | Why | Report line |
| --- | --- | --- | --- |
| identity columns, and a sequence a BEFORE INSERT trigger assigns | GENERATED BY DEFAULT ON NULL AS 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 | Oracle 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), [SQL Server](/docs/types/oracle-to-sql-server)
- Into Oracle from [MySQL](/docs/types/mysql-to-oracle), [MariaDB](/docs/types/mariadb-to-oracle), [PostgreSQL](/docs/types/postgresql-to-oracle), [SQL Server](/docs/types/sql-server-to-oracle), [SQLite](/docs/types/sqlite-to-oracle)
- [Every pair](/docs/types#from-one-database-to-another)
