SQLines tools can help you transfer data, convert database schema (DDL), views, PL/SQL stored procedures, functions, packages, triggers, queries and SQL scripts from Oracle to MySQL.
Databases:
Converting identifiers:
| Oracle | MySQL | ||
| First character | Letter | Letter or digit | |
| Subsequent characters | Letter, digit, _ , # and $ | Letter, digit, _ and $ | |
| Identifier quote character | " (double quotes) | ` (backtick) | " if ANSI_QUOTES is set (not set by default) |
Namespaces:
| Oracle | MySQL | |
| Tables, views, procedures, functions, packages, sequences | Share the same namespace | Tables, views |
| Constraints, indexes, triggers | Have own namespace | Constraints, indexes, triggers |
Operators:
| Oracle | MySQL | |||
| 1 | || Operator | String concatenation | CONCAT function ![]() |
|
| 2 | + and - Operators for datetime | Datetime arithmetic | Interval expressions and functions |
|
| 3 | exp IS JSON | Check if JSON is valid | JSON_VALID(exp) | |
Converting character data types:
| Oracle | MySQL | |||
| 1 | CHAR(n) | Fixed-length string, 1 ⇐ n ⇐ 2000 | CHAR(n) | 0 ⇐ n ⇐ 255 |
| 2 | NVARCHAR2(n) | Variable-length Unicode string, 1 ⇐ n ⇐ 32,767 | NVARCHAR(n) | 0 ⇐ n ⇐ 65,535 |
| 3 | VARCHAR(n) | Synonym for VARCHAR2 | VARCHAR(n) | |
| 4 | VARCHAR2(n) | Variable-length string, 1 ⇐ n ⇐ 32,767 | VARCHAR(n) | 0 ⇐ n ⇐ 65,535 |
Converting numeric data types:
| Oracle | MySQL | |||
| 1 | BINARY_FLOAT | 32-bit floating-point number | FLOAT | |
| 2 | BINARY_DOUBLE | 64-bit floating-point number | DOUBLE | |
| 3 | DECIMAL(p,s) | Fixed-point number | DECIMAL(p,s) | |
| 4 | DOUBLE PRECISION | Floating-point number | DOUBLE PRECISION | |
| 5 | FLOAT(p) | Floating-point number | DOUBLE | |
| 6 | INTEGER, INT | 38 digits integer | INT | DECIMAL(38) |
| 7 | NUMBER(p,0), NUMBER(p) | 8-bit integer, 1 ⇐ p < 3 | TINYINT | (0 to 255) |
| 16-bit integer, 3 ⇐ p < 5 | SMALLINT | |||
| 32-bit integer, 5 ⇐ p < 9 | INT | |||
| 64-bit integer, 9 ⇐ p < 19 | BIGINT | |||
| Fixed-point number, 19 ⇐ p ⇐ 38 | DECIMAL(p) | |||
| 8 | NUMBER(p,s) | Fixed-point number, s > 0 | DECIMAL(p,s) | |
| 9 | NUMBER, NUMBER(*) | Floating-point number | DECIMAL(p,s) | DOUBLE |
| 10 | NUMERIC(p,s) | Fixed-point number | NUMERIC(p,s) | |
| 11 | REAL | Floating-point number | DOUBLE | |
| 12 | SMALLINT | 38 digits integer | DECIMAL(38) | |
Converting date and time data types:
| Oracle | MySQL | |||
| 1 | DATE | Date and time | DATETIME | |
| 2 | INTERVAL YEAR(p) TO MONTH | Date interval | VARCHAR(30) | |
| 3 | INTERVAL DAY(p) TO SECOND(s) | Date and time interval | VARCHAR(30) | |
| 4 | TIMESTAMP(p) | Date and time with fraction, 0 ⇐ p ⇐ 9, default is 6 | DATETIME(p), 0 ⇐ p ⇐ 6 |
|
| 5 | TIMESTAMP(p) WITH TIME ZONE | Date and time with fraction and time zone | DATETIME(p) |
|
Converting other data types:
| Oracle | MySQL | |||
| 1 | BFILE | Pointer to binary file, ⇐ 4G | VARCHAR(255) | |
| 2 | BLOB | Binary large object, ⇐ 4G | LONGBLOB | |
| 3 | CLOB | Character large object, ⇐ 4G | LONGTEXT | |
| 4 | LONG | Character data, ⇐ 2G | LONGTEXT | |
| 5 | LONG RAW | Binary data, ⇐ 2G | LONGBLOB | |
| 6 | NCHAR(n) | Fixed-length UTF-8 string, 1 ⇐ n ⇐ 255 | NCHAR(n) | |
| 7 | NCHAR(n) | Fixed-length UTF-8 string, 256 ⇐ n ⇐ 2000 | NVARCHAR(n) | |
| 8 | NCHAR VARYING(n) | Varying-length UTF-8 string, 1 ⇐ n ⇐ 4000 | NCHAR VARYING(n) | |
| 9 | NCLOB | Variable-length Unicode string, ⇐ 4G | LONGTEXT | |
| 10 | RAW(n) | Variable-length binary string, 1 ⇐ n ⇐ 2000 | VARBINARY(n) | |
| 11 | ROWID | Physical row address | CHAR(10) | |
| 12 | UROWID(n) | Logical row addresses, 1 ⇐ n ⇐ 4000 | VARCHAR(n) | |
| 13 | XMLTYPE | XML data | LONGTEXT | |
Converting string functions:
Converting date and time functions:
| Oracle | MySQL | |||
| 1 | ADD_MONTHS(date, num) | Add num months to date | TIMESTAMPADD(MONTH, num, date) | |
| 2 | EXTRACT(part FROM date) | Extract datetime part | EXTRACT(part FROM date) | |
| 3 | LAST_DAY(date) | Get last day of month (includes time) | LAST_DAY(date) | Date only |
| 4 | NEXT_DAY(date, weekday) | Get next weekday (includes time) | DATE_ADD and WEEKDAY expression | |
| 5 | SYSDATE | Get current date and time | SYSDATE() | Includes time |
| 6 | SYSTIMESTAMP | Get current datetime | NOW(6) | |
| 7 | TO_DATE(string, format) | Convert string to datetime | STR_TO_DATE(string, format) |
|
| 8 | TRUNC(datetime) | Truncate datetime value | CAST and DATE_FORMAT | |
Numeric functions:
| Oracle | MySQL | ||
| 1 | ROUND(exp, len) | Round to specified precision | ROUND(exp, len) |
Converting NULL processing functions:
| Oracle | MySQL | |||
| 1 | NVL(exp, replacement) | Replace NULL with the specified value | IFNULL(exp, replacement) | |
Aggregation and window functions:
| Oracle | MySQL | |||
| 1 | DENSE_RANK() OVER (...) | Assign rank without gaps | DENSE_RANK() OVER (...) |
|
| 2 | RANK() OVER (...) | Assign rank with gaps | RANK() OVER (...) |
|
Converting math functions:
| Oracle | MySQL | |||
| 1 | POWER(value, n) | Raise value to the nth power | POWER(value, n) | |
Converting LOB functions:
| Oracle | MySQL | |||
| 1 | EMPTY_BLOB() | Get empty BLOB locator | x'' | |
| 2 | EMPTY_CLOB() | Get empty CLOB locator | '' | |
Converting system functions:
| Oracle | MySQL | |||
| 1 | SYS_CONTEXT('USERENV', 'OS_USER') | Get OS user | USER() |
|
| 1 | SYS_CONTEXT('USERENV', 'SESSION_USER') | Get current user | USER() | |
| 2 | USER | Get current user | USER() | |
Converting other functions:
| Oracle | MySQL | ||
| 1 | SYS_GUID() | Generate UUID | UUID() |
Converting built-in SQL functions from Oracle to MySQL:
Converting queries:
| Oracle | MySQL | |||
| 1 | SELECT * FROM (SELECT ...) | Subquery alias is optional | SELECT * FROM (SELECT ...) t | Alias required |
| 2 | t1 JOIN t2 USING (column_name) | USING clause for joins | t1 JOIN t2 USING (column_name) | |
| 3 | CROSS JOIN | Cartesian product | CROSS JOIN | |
| 4 | CONNECT BY PRIOR | Hierarchical queries | Recursive Common Table Expressions (CTE) | |
| 5 | ORDER BY col NULLS FIRST | LAST | Order of NULLs | ORDER BY col |
|
Row limitation:
| Oracle | MySQL | |||
| 1 | OFFSET k FETCH FIRST n ROWS ONLY | Row limiting | LIMIT k, n | |
| 2 | ROWNUM = 1 | Return 1 row only | LIMIT 1 | |
| ROWNUM <= n | Row limit | LIMIT n | ||
| ROWNUM < n | LIMIT n - 1 | |||
| ROWNUM < (10+2) | Arbitrary expression | Only integer is allowed |
||
Other clauses:
| Oracle | MySQL | |||
| 1 | FOR UPDATE | Lock selected rows | FOR UPDATE | |
| 2 | SKIP LOCKED | Skip locked rows | Not supported by MySQL, commented | |
Converting CREATE TABLE statement keywords and clauses:
| Oracle | MySQL | |||
| 1 | GENERATED AS IDENTITY | Identity column | AUTO_INCREMENT | |
| 2 | CONSTRAINT name NOT NULL | Named NOT NULL constraint | NOT NULL | |
| 3 | DEFAULT ON NULL exp | Default when NULL is inserted | DEFAULT exp |
|
| 4 | ENABLE | Constraint enabled attribute | Removed | |
| 5 | col AS (exp) | Computed column | type col AS (exp) | Data type must be specified |
Temporary tables:
| Oracle | MySQL | ||
| 1 | CREATE GLOBAL TEMPORARY TABLE | Global temporary table | CREATE TEMPORARY TABLE |
| 2 | schema.name | Qualified object name | db_name.name |
Partitioned tables:
| Oracle | MySQL | ||
| 1 | PARTITION BY RANGE | Range partitions | PARTITION BY RANGE |
| 2 | PARTITION BY LIST | List partitions | PARTITION BY LIST |
Converting CREATE INDEX statement keywords and clauses:
| Oracle | MySQL | ||
| 1 | CREATE INDEX schema.index_name | CREATE INDEX index_name | Can contain index name only |
Converting views from Oracle to MySQL:
| Oracle | MySQL | ||
| 1 | CREATE OR REPLACE VIEW name | CREATE OR REPLACE VIEW name | |
| 2 | FORCE keyword | Create view even if tables not exist | Removed |
| 3 | WITH READ ONLY | Clause not supported, removed |
|
Oracle DROP SEQUENCE, CREATE SEQUENCE and NEXTVAL emulation in MySQL using stored procedures and user-defined functions.
| Oracle | MySQL | |
| 1 | CREATE SEQUENCE name START WITH start INCREMENT BY inc | CreateSequence('name', start, inc) |
| 2 | DROP SEQUENCE name | DropSequence('name') |
| 3 | name.NEXTVAL | NextVal('name') |
Converting stored procedures from Oracle to MySQL:
| Oracle | MySQL | |||
| 1 | CREATE OR REPLACE PROCEDURE | DROP PROCEDURE IF EXISTS and CREATE PROCEDURE | ||
| 2 | param IN | OUT | IN OUT datatype | Parameter definition | IN | OUT | INOUT param datatype(length) | |
| 3 | IS | AS | Removed | ||
| 4 | Variable declaration is before BEGIN | Variable declaration is after BEGIN | ||
| 5 | END sp_name | END | ||
For more information, see Conversion of PL/SQL Statements.
Converting user-defined functions:
| Oracle | MySQL | |||
| 1 | CREATE OR REPLACE FUNCTION | DROP FUNCTION IF EXISTS and CREATE FUNCTION | ||
| 2 | param IN | OUT | IN OUT datatype | Parameter definition | param datatype(length) | |
| 3 | RETURN datatype | Return value | RETURNS datatype(length) | |
| 4 | IS | AS | Removed | ||
| 5 | Variable declaration is before BEGIN | Variable declaration is after BEGIN | ||
| 6 | END func_name | END | ||
For more information, see Conversion of PL/SQL Statements.
Converting triggers from Oracle to MySQL:
| Oracle | MySQL | |||
| 1 | CREATE OR REPLACE TRIGGER | DELIMITER // DROP TRIGGER IF EXISTS and CREATE TRIGGER |
||
| 2 | BEFORE | AFTER | INSTEAD OF | BEFORE | AFTER | ||
| 3 | INSERT OR UPDATE OR DELETE | Multiple events in one trigger | Only one event in trigger |
|
| 4 | ON table | ON table | ||
| 5 | REFERENCING OLD AS old_name NEW AS new_name | Clause is not supported, OLD and NEW used | ||
| 6 | :NEW.col, :OLD.col | Referencing column values | NEW.col, OLD.col | |
| 7 | Statement-level trigger by default | Statement-level triggers are not supported |
||
| 8 | FOR EACH ROW | Row-level trigger | FOR EACH ROW | Must be specified |
| 9 | BEGIN stmt; … END; / | BEGIN stmt; … END; // DELIMITER ; | ||
For more information, see a trigger conversion example and Conversion of PL/SQL Statements.
Converting PL/SQL statements and clauses from Oracle to MySQL:
Cursor attributes:
| Oracle | MySQL | |||
| 1 | cursor%FOUND | Cursor fetched | NOT_FOUND = 0 | HANDLER FOR NOT FOUND |
| 2 | cursor%NOTFOUND | No row found | NOT_FOUND = 1 | |
Flow-of-control statements:
| Oracle | MySQL | ||
| 1 | GOTO label | Jump to label | LEAVE label and BEGIN-END block |
Executing stored procedures from a PL/SQL block:
| Oracle | MySQL | ||
| 1 | sp_name(param1, ...) | Execute procedure | CALL sp_name(param1, ...) |
| sp_name | Procedure without parameters | CALL sp_name | |
| sp_name(param1 => value1, ...) | Procedure with named parameters | sp_name(value1, ...) |
|
Error handling:
| Oracle | MySQL | ||
| 1 | RAISE_APPLICATION_ERROR(-20xxx, text) | Raise user error | SIGNAL SQLSTATE '45xxx' SET MESSAGE_TEXT text |
EXCEPTION block:
| Oracle | MySQL | ||
| 1 | BEGIN stmts EXCEPTION … END | Exception block structure | BEGIN DECLARE HANDLER … stmts END |
| 2 | WHEN DUP_VAL_ON_INDEX | Duplicate key | DECLARE EXIT HANDLER FOR SQLSTATE '23000' |
| 3 | WHEN NO_DATA_FOUND | No rows found | DECLARE EXIT HANDLER FOR NOT FOUND |
| 4 | WHEN OTHERS | All exceptions | DECLARE EXIT HANDLER FOR SQLEXCEPTION |
| 5 | RAISE | Re-raise the current exception | RESIGNAL |
Table manipulation statements:
| Oracle | MySQL | |||
| 1 | ALTER TABLE ... ADD FOREIGN KEY | Add foreign key | ALTER TABLE ... ADD FOREIGN KEY Data type issues |
|
| 2 | ALTER TABLE ... ADD UNIQUE ... USING INDEX | Add unique constraint with existing index | Index commented |
|
| 3 | ALTER TABLE ... MODIFY (coldef, ...) | Modify column(s) | ALTER TABLE ... MODIFY coldef, ... |
|
Converting SQL statements and clauses:
| Oracle | MySQL | |||
| 1 | ALTER TRIGGER name ENABLE | Commented | ||
| 2 | COMMENT ON COLUMN table.column IS 'string' | Moved to CREATE TABLE as COMMENT 'string' clause | ||
| 3 | COMMENT ON TABLE table IS 'string' | ALTER TABLE table COMMENT 'string' | ||
| 4 | CREATE SEQUENCE | CreateSequence stored procedure | ||
| 5 | DELETE [FROM] table | Delete rows | DELETE FROM table | FROM keyword is required |
| 6 | DROP SEQUENCE | DropSequence stored procedure | ||
| 7 | LOCK TABLE name IN EXCLUSIVE MODE | LOCK TABLES name WRITE | ||
| LOCK TABLE name IN SHARE MODE | LOCK TABLES name READ | |||
System and Control statements:
| Oracle | MySQL | |||
| 1 | ALTER USER | Alter user | ALTER USER |
|
| 2 | CREATE USER | Create user | CREATE USER |
|
| 3 | GRANT | Grant privileges | GRANT |
|
Converting built-in PL/SQL packages:
| Oracle | MySQL | ||
| 1 | DBMS_SQL | Dynamic SQL | PREPARE and EXECUTE statements |
Converting Oracle SQL*Plus commands:
| Oracle | MySQL | ||
| 1 | REM | REMARK text | Single line comment | -- text |
| 2 | SET DEFINE ON | OFF | Variable substitution | Commented |
Oracle features that may require significant re-design when migrating to MySQL: