---
title: "Migrate MariaDB to Oracle in your browser"
description: "Migrate a MariaDB database to Oracle: convert its dump into a script with the same tables, keys, sequences and data, and a report of every change."
canonical: https://intosql.com/mariadb-to-oracle
last_updated: 2026-10-15
---

# Migrate MariaDB to Oracle in your browser

Drop a dump from mariadb-dump, mysqldump, phpMyAdmin or Adminer, as .sql or .sql.gz, and download a script for Oracle with the same tables, keys, indexes and data. Every value Oracle can't hold as it is, and every object it doesn't carry, is listed in the report.

[MariaDB to Oracle migration guide](https://intosql.com/docs/migrations/mariadb-to-oracle)

[MariaDB to Oracle data types](https://intosql.com/docs/types/mariadb-to-oracle)

## What changes from MariaDB to Oracle

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

| In MariaDB | In Oracle | Report line |
| --- | --- | --- |
| TINYINT(1), BOOL | NUMBER(1) with a CHECK of 0 and 1 when every value is 0 or 1, else NUMBER(3) | `bool_kept_numeric` |
| UNSIGNED integers | NUMBER wide enough for the range, with a CHECK that it isn't negative |  |
| ZEROFILL and display widths | dropped | `zerofill_dropped` |
| FLOAT(M,D) | BINARY_FLOAT or BINARY_DOUBLE, without the scale | `float_scale_dropped` |
| DECIMAL(p,s) | NUMBER(p,s) up to 38 digits; VARCHAR2 beyond | `decimal_as_text` |
| BIT(1), BIT(n) | NUMBER(1), NUMBER(19) up to 63 bits, NUMBER(20) for BIT(64) |  |
| zero, partial or impossible dates (0000-00-00, 2024-02-30) | NULL | `invalid_date_null` |
| NOT NULL columns with values that become NULL | NOT NULL dropped | `not_null_relaxed` |
| empty strings and empty binary values | NULL | `empty_string_null` |
| DEFAULT '0000-00-00' | no default | `zero_date_default` |
| TIME | INTERVAL DAY TO SECOND, which holds durations |  |
| YEAR | NUMBER(4) with a CHECK of its range |  |
| CHAR(n), VARCHAR(n) | VARCHAR2(n CHAR), counting characters |  |
| VARCHAR(n) and TEXT longer than 4000 bytes | CLOB | `text_as_lob` |
| DATETIME | TIMESTAMP |  |
| TIMESTAMP | TIMESTAMP WITH TIME ZONE in the zone the dump states, UTC when it states none | `timestamp_zone_assumed` |
| ENUM | VARCHAR2 with a CHECK of its values |  |
| ENUM holding '' (MySQL's error value) | NULL |  |
| ENUM holding values outside its list | no CHECK | `enum_check_skipped` |
| SET | VARCHAR2 as MySQL writes it ('a,b') |  |
| JSON | CLOB |  |
| NUL bytes in text | kept |  |
| text that isn't valid in its character set | the bad bytes as the replacement character | `invalid_utf8_replaced` |
| text decoded twice (Ã±) | copied as it is | `mojibake_suspected` |
| AUTO_INCREMENT | GENERATED BY DEFAULT ON NULL AS IDENTITY, restarted past the copied ids |  |
| MyISAM AUTO_INCREMENT on the second column of a key | one counter for the table | `myisam_group_autoincrement` |
| ON UPDATE CURRENT_TIMESTAMP | a BEFORE UPDATE trigger | `on_update_trigger` |
| generated columns | virtual columns | `stored_as_virtual` |
| generated columns with functions Oracle lacks | a plain column | `generated_not_translated` |
| INVISIBLE columns | INVISIBLE columns |  |
| CHECK constraints | translated, inline in CREATE TABLE |  |
| CHECK constraints with functions Oracle lacks | not created | `check_skipped` |
| CHECK ... NOT ENFORCED | not created | `check_not_enforced` |
| defaults with functions Oracle lacks | no default | `default_not_translated` |
| keys and indexes on a prefix, c(20) | an index on SUBSTR of the column | `prefix_unique` |
| FULLTEXT indexes | not created | `fulltext_not_created` |
| SPATIAL indexes | not created | `spatial_index_not_created` |
| functional indexes, and indexes on whole CLOB or BLOB columns | not created | `index_skipped` |
| foreign keys | after the data ENABLE NOVALIDATE, then validated with a warning on orphans |  |
| ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULT | dropped | `foreign_key_action_unsupported` |
| foreign keys to columns without a unique key | not created | `foreign_key_skipped` |
| table and column names | uppercase when they are plain names, else as written | `identifier_renamed` |
| names over 128 bytes | shortened | `name_shortened` |
| GEOMETRY, POINT, POLYGON... | BLOB holding WKB | `geometry_as_blob` |
| INET4, INET6, UUID (MariaDB) | VARCHAR2(39), VARCHAR2(36) |  |
| BINARY, VARBINARY, BLOB | RAW up to 2000 bytes, else BLOB |  |
| PARTITION BY | one table | `partitions_dropped` |
| WITH SYSTEM VERSIONING (MariaDB) | a table with the current rows | `system_versioning_dropped` |
| MyISAM, MEMORY and other engines | a regular table | `engine_dropped` |
| views, triggers, procedures, functions and events | listed in the report | `not_converted_objects` |
| dumps without CREATE TABLE | types read from the values | `no_schema` |
| geometries in a dump without CREATE TABLE | BLOB holding WKB | `geometry_inferred` |
| _ci collations | exact comparison | `case_insensitive_collation` |
| SET NAMES utf8 from utf8mb4 tables | converted, with a warning | `dump_lost_four_byte_chars` |
| dumps without SET NAMES whose text isn't UTF-8 | read as Latin-1 (Windows-1252) | `charset_guessed` |
| sjis, cp932, gbk, big5 dumps | read as UTF-8, with a warning | `unsupported_charset` |
| UNHEX('..'), CONVERT(b'..', UNSIGNED), CONVERT(".." USING x), ST_GeomFromText('..') in rows | evaluated |  |
| other expressions in rows | NULL | `expression_value` |
| DEFAULT in VALUES | the column's default value | `default_keyword_filled` |
| DEFAULT in VALUES without a literal default | NULL | `default_keyword_null` |
| REPLACE and INSERT IGNORE | plain rows | `replace_as_insert` |
| types IntoSQL doesn't know | CLOB | `unknown_type` |
| values that don't fit their column | NULL | `invalid_value_null` |
| unreadable geometries | NULL | `bad_geometry` |
| dumps of several databases | one schema, each table named after its database first | `databases_merged` |
| CREATE SEQUENCE (MariaDB) | CREATE SEQUENCE, at the value it had reached |  |
| VECTOR(n) (MariaDB 11.7+) | CLOB with the floats as a JSON array | `type_replaced` |

## Load the script into Oracle

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.

```shell
NLS_LANG=.AL32UTF8 sqlplus -S -L user@//localhost/mydb @mariadb.oracle.sql
```

Foreign keys are added ENABLE NOVALIDATE, so new rows are checked at once, and then validated. If an old row points to a row that doesn't exist, the script says which constraint and leaves it unvalidated, instead of failing half way.

For a large dump, run SQL*Plus on the same machine as the database. The script commits every 100 rows. The user that runs it needs CREATE TABLE, CREATE SEQUENCE, CREATE TRIGGER and CREATE PROCEDURE, and quota on its tablespace.

## Dump MariaDB for the best result

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

- --default-character-set=utf8mb4 keeps emoji and other 4-byte characters, which a utf8mb3 dump loses before the converter sees it.
- --hex-blob writes binary columns and VECTOR values as hexadecimal, which survives copying between systems.
- --routines --triggers --events add those objects to the dump, so the report can list them.

## What isn't converted

Views, triggers, stored procedures, functions and events are written in MariaDB's own language. They are listed in the report by name, never dropped silently, so you can rewrite them for Oracle.

## Questions about MariaDB to Oracle

### 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.

### Which MariaDB versions can the dump come from?

Dumps from mariadb-dump and mysqldump on MariaDB 10.3 to 12, with one INSERT per table or one per row. Every test dump comes from MariaDB 10.11, 11.4 and 11.8 and is compared with its source cell by cell.

### Are UUID, INET6, JSON and VECTOR columns kept?

UUID and INET columns become VARCHAR2, JSON CLOB, and VECTOR a JSON array of its floats. Zero dates become NULL, and so do empty strings, as Oracle stores them.

### Are AUTO_INCREMENT values and sequences kept?

Yes. Each AUTO_INCREMENT column becomes an identity column that continues after the highest id. Sequences become Oracle sequences, and defaults that draw from one keep drawing from it.

### What about stored procedures and triggers?

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

### Which Oracle versions does the script load on?

Oracle 19c and later. Every test dump loads on 21c and 23ai, stopping at the first error if anything goes wrong.

## From MariaDB

- [MariaDB to PostgreSQL](https://intosql.com/mariadb-to-postgresql)
- [MariaDB to MySQL](https://intosql.com/mariadb-to-mysql)
- [MariaDB to MariaDB](https://intosql.com/mariadb-to-mariadb)
- [MariaDB to SQLite](https://intosql.com/mariadb-to-sqlite)
- [MariaDB to SQL Server](https://intosql.com/mariadb-to-sql-server)

## Into Oracle

- [MySQL to Oracle](https://intosql.com/mysql-to-oracle)
- [PostgreSQL to Oracle](https://intosql.com/postgresql-to-oracle)
- [SQL Server to Oracle](https://intosql.com/sql-server-to-oracle)
- [SQLite to Oracle](https://intosql.com/sqlite-to-oracle)
- [Oracle to Oracle](https://intosql.com/oracle-to-oracle)

## Guide and every pair

- [Oracle to MariaDB](https://intosql.com/oracle-to-mariadb)
- [MariaDB to Oracle migration guide](https://intosql.com/docs/migrations/mariadb-to-oracle)
- [MariaDB to Oracle data types](https://intosql.com/docs/types/mariadb-to-oracle)
- [Every database pair](https://intosql.com/database-migration)
