Este documento forma parte de una serie que proporciona información y directrices clave relacionadas con la planificación y la realización de migraciones de bases de datos Oracle® 11g/12c a instancias de segunda generación de Cloud SQL para MySQL versión 5.7. La serie incluye las siguientes partes:
- Migrar usuarios de Oracle a Cloud SQL para MySQL: terminología y funciones
- Migrar usuarios de Oracle a Cloud SQL para MySQL: tipos de datos, usuarios y tablas
- Migrar usuarios de Oracle a Cloud SQL para MySQL: consultas, procedimientos almacenados, funciones y activadores (este documento)
- Migrar usuarios de Oracle a Cloud SQL para MySQL: seguridad, operaciones, monitorización y registro
Consultas
Oracle y Cloud SQL para MySQL admiten el estándar ANSI SQL. Por lo general, la migración de instrucciones SQL es sencilla si solo se usan elementos de sintaxis básicos (por ejemplo, si no se especifican funciones escalares ni ninguna otra función ampliada de Oracle). En la siguiente sección se describen los elementos de consulta de Oracle habituales y sus equivalentes en Cloud SQL para MySQL.
Sintaxis básica de SELECT y FROM
Nombre de la función o de la sintaxis de Oracle | Descripción general o implementación de Oracle | Compatibilidad con MySQL | Solución correspondiente o alternativa de MySQL |
---|---|---|---|
Sintaxis básica de SQL para recuperar datos | SELECT FROM WHERE GROUP BY HAVING ORDER BY |
Sí | SELECT FROM WHERE GROUP BY HAVING ORDER BY |
SELECT para la impresión de salida |
SELECT 1 FROM DUAL |
Sí | SELECT 1 OR SELECT 1 FROM DUAL |
Alias de columna | SELECT COL1 AS C1 |
Sí | SELECT COL1 AS C1 OR SELECT COL1 C1 |
Nombre de la tabla distinción entre mayúsculas y minúsculas |
No se distingue entre mayúsculas y minúsculas (por ejemplo, el nombre de la tabla puede ser orders
o ORDERS ). |
No | Distinguen entre mayúsculas y minúsculas según el nombre de tabla definido (por ejemplo, el nombre de tabla solo puede ser orders o ORDERS ). |
Puedes consultar más detalles sobre la sintaxis de SELECT
de MySQL.
- Vistas insertadas
- Las vistas insertadas (también conocidas como tablas derivadas) son instrucciones
SELECT
que se encuentran en la cláusulaFROM
y se usan como subconsultas. - Las vistas insertadas pueden simplificar las consultas complejas eliminando cálculos compuestos o operaciones de unión, al tiempo que condensan varias consultas independientes en una sola consulta simplificada.
- Nota sobre las conversiones: Las vistas insertadas de Oracle no requieren el uso de alias, mientras que MySQL sí requiere alias específicos para cada vista insertada.
- Las vistas insertadas (también conocidas como tablas derivadas) son instrucciones
En la siguiente tabla se muestra un ejemplo de conversión de Oracle a MySQL como vista insertada.
Oracle 11g/12c |
---|
SQL> SELECT FIRST_NAME, DEPARTMENT_ID, SALARY, DATE_COL FROM EMPLOYEES, (SELECT SYSDATE AS DATE_COL FROM DUAL); La salida es similar a la siguiente: FIRST_NAME DEPARTMENT_ID SALARY DATE_COL -------------------- ------------- ---------- --------- Steven 90 24000 30-JUL-19 Neena 90 17000 30-JUL-19 Lex 90 17000 30-JUL-19 |
Cloud SQL para MySQL 5.7 |
Sin alias para la vista insertada:mysql> SELECT FIRST_NAME, DEPARTMENT_ID, SALARY, DATE_COL FROM EMPLOYEES, (SELECT SYSDATE() AS DATE_COL FROM DUAL); Añadir un alias a la vista insertada: mysql> SELECT FIRST_NAME, DEPARTMENT_ID, SALARY, DATE_COL FROM EMPLOYEES, (SELECT SYSDATE() AS DATE_COL FROM DUAL) AS A1; La salida es similar a la siguiente: +-------------+---------------+----------+---------------------+ | FIRST_NAME | DEPARTMENT_ID | SALARY | DATE_COL | +-------------+---------------+----------+---------------------+ | Steven | 90 | 23996.00 | 2019-07-30 09:28:00 | | Neena | 90 | 22627.00 | 2019-07-30 09:28:00 | | Lex | 90 | 22627.00 | 2019-07-30 09:28:00 | |
Instrucciones JOIN
MySQL admite las instrucciones JOIN
de Oracle JOIN
, excepto la cláusula FULL JOIN
. Además, las instrucciones JOIN
de MySQL admiten el uso de sintaxis alternativas, como la cláusula USING
, la cláusula
WHERE
en lugar de la cláusula ON
y el uso de SUBQUERY
en la instrucción JOIN
.
En la siguiente tabla se muestra un ejemplo de conversión de JOIN.
Tipo de JOIN de Oracle | Admitido por MySQL | Sintaxis de JOIN de MySQL |
---|---|---|
INNER JOIN |
Sí | SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E JOIN DEPARTMENTS D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID; |
CROSS JOIN |
Sí | SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E CROSS JOIN DEPARTMENTS D |
FULL JOIN |
No | Para solucionar este problema, puedes usar UNION con las instrucciones LEFT y RIGHT JOIN . |
LEFT JOIN [ OUTER ] |
Sí | SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E LEFT JOIN DEPARTMENTS D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID; |
RIGHT JOIN [ OUTER ] |
Sí | SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E RIGHT JOIN DEPARTMENTS D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID; |
SUBQUERY |
Sí | SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E JOIN (SELECT * FROM DEPARTMENTS)D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID; |
UNION, UNION ALL, INTERSECT y MINUS
MySQL no admite las funciones INTERSECT
y MINUS
de Oracle, excepto las funciones UNION
y UNION ALL
:
UNION
: adjunta los conjuntos de resultados de dos o más instruccionesSELECT
y elimina los registros duplicados.UNION ALL
: adjunta los conjuntos de resultados de dos o más instruccionesSELECT
sin eliminar los registros duplicados.INTERSECT
: devuelve la intersección de dos o másSELECT
instrucciones solo si existe un registro en ambos conjuntos de datos.MINUS
: compara dos o más instruccionesSELECT
y devuelve solo las filas distintas de la primera consulta que no devuelven las otras instrucciones.
Notas de conversión
Cuando conviertas funciones de Oracle INTERSECT
y MINUS
a MySQL, usa instrucciones JOIN
y IN
y EXISTS
como solución alternativa.
Ejemplos
Función de Oracle | Implementación de Oracle | Compatibilidad con MySQL | Solución correspondiente o alternativa de MySQL |
---|---|---|---|
UNION |
SELECT COL1 FROM TBL1 UNION SELECT COL1 FROM TBL2 |
Sí | SELECT COL1 FROM TBL1 UNION SELECT COL1 FROM TBL2 |
UNION ALL |
SELECT COL1 FROM TBL1 UNION ALL SELECT COL1 FROM TBL2 |
Sí | SELECT COL1 FROM TBL1 UNION ALL SELECT COL1 FROM TBL2 |
INTERSECT |
SELECT COL1 FROM TBL1 INTERSECT SELECT COL1 FROM TBL2 |
No | SELECT COL1 FROM TBL1 WHERE COL1 IN (SELECT COL1 FROM TBL2) |
MINUS |
SELECT COL1 FROM TBL1 MINUS SELECT COL1 FROM TBL2 |
No | SELECT A.COL1 FROM TBL1 A LEFT JOIN TBL2 B ON USING(COL1) WHERE B.COL1 IS NULL |
Funciones escalares (de una sola fila) y de grupo
MySQL proporciona una amplia lista de funciones escalares (de una sola fila) y de agregación. Algunas funciones de MySQL son similares a sus equivalentes de Oracle (por nombre y funcionalidad, o con un nombre diferente pero con una funcionalidad similar). Aunque las funciones de MySQL pueden tener nombres idénticos a sus equivalentes de Oracle, pueden mostrar funcionalidades diferentes.
En las siguientes tablas se describe en qué casos Oracle y MySQL son equivalentes por nombre y funcionalidad (especificado con "Sí") y en qué casos se recomienda una conversión (todos los casos que no sean "Sí").
Funciones de caracteres
Función de Oracle | Especificación o implementación de funciones de Oracle | Equivalente de MySQL | Función correspondiente de MySQL | Especificación o implementación de la función MySQL |
---|---|---|---|---|
CONCAT(str1,str2) |
Devuelve str1 concatenado con str2:CONCAT('A', 1) = A1 |
Sí | CONCAT |
Equivalente a Oracle:CONCAT('A', 1) = A1 |
LOWER/UPPER |
Devuelve el carácter con todas las letras en minúsculas o mayúsculas:LOWER('SQL') = sql |
Sí | LOWER/UPPER |
Equivalente a Oracle:LOWER('SQL') = sql |
LPAD/RPAD(expr1,n,expr2) |
Devuelve expr1, con relleno a la izquierda o a la derecha hasta alcanzar una longitud de n caracteres
con la secuencia de caracteres de expr2:LPAD('A',3,'*') = **A |
Sí | LPAD/RPAD |
Equivalente a Oracle:LPAD('A',3,'*') = **A |
SUBSTR(char,p,n) |
Devuelve una parte de char, que empieza en la posición del carácter p y tiene una longitud de n caracteres:SUBSTR('MySQL', 3, 3) = SQL |
Sí | SUBSTR(char,p,n) |
Equivalente a Oracle:SUBSTR('MySQL', 3, 3) = SQL |
INSTR(index,str) |
Devuelve la posición (índice) de la cadena str:INSTR('MySQL', 'y') = 2 |
Sí | INSTR |
Equivalente a Oracle:INSTR('MySQL', 'y') = 2 |
REPLACE(char,str1,str2) |
Devuelve el carácter con cada instancia de una cadena de búsqueda sustituida por una cadena de sustitución: REPLACE('ORADB', 'ORA', 'MySQL') |
Sí | REPLACE(char,str1,str2) |
Equivalente a Oracle:REPLACE('ORADB', 'ORA', 'MySQL') |
TRIM(str) |
Recortar los caracteres iniciales o finales (o ambos) de una cadena:TRIM(both '-' FROM '-MySQL-') = MySQL |
Sí | TRIM(str) |
Equivalente a Oracle:TRIM(both '-' FROM '-MySQL-') = MySQL |
LTRIM/RTRIM(str) |
Elimina del extremo izquierdo o derecho de la cadena todos los caracteres que
aparezcan en la búsqueda:LTRIM(' MySQL', ' ') = MySQL |
Parcialmente | LTRIM/RTRIM(str) |
Función R/LTRIM de Oracle, excepto una sustitución del parámetro (espacio en blanco o cadena). MySQL R/LTRIM solo elimina los espacios en blanco y acepta únicamente la cadena de entrada:LTRIM(' MySQL') = MySQL |
ASCII(char) |
Devuelve la representación decimal en el conjunto de caracteres de la base de datos del primer carácter de char: ASCII('A') = 65 |
Sí | ASCII(char) |
Equivalente a Oracle:ASCII('A') = 65 |
CHR(char) |
Devuelve el valor del código ASCII, que es un valor numérico entre 0 y 225,
de un carácter:CHR(65) = A |
Parcialmente con un nombre de función diferente | CHAR(char) |
MySQL usa la función CHAR para la misma función, por lo que debes modificar el nombre de la función:CHAR(65) = A |
LENGTH(str) |
Devuelve la longitud de una cadena determinada:LENGTH ('MySQL') = 5 |
Sí | LENGTH(str) |
Equivalente a Oracle:LENGTH('MySQL') = 5 |
REGEXP_REPLACE(str1,expr,str2) |
Buscar una cadena con un patrón de expresión regular:REGEXP_REPLACE('John', '[hn].', '1') = Jo1 |
No | N/A | Solo se admite a partir de la versión 8 de MySQL. Como solución alternativa, usa la función REPLACE si es posible o convierte a la capa de aplicación. |
REGEXP_SUBSTR(str,expr) |
Amplía la funcionalidad de la función SUBSTR buscando en una cadena un patrón de expresión regular:REGEXP_SUBSTR('https://console.cloud.google.com/sql/instances','https://([[:alnum:]]+\.?){3,4}/?') = https://console.cloud.google.com/ |
No | N/A | Solo se admite a partir de la versión 8 de MySQL. Como solución alternativa, usa la función SUBSTR si es posible o convierte la función a la capa de aplicación. |
REGEXP_COUNT(str,expr) |
Devuelve el número de veces que aparece un patrón en una cadena de origen. | No | N/A | Para encontrar una solución alternativa, convierte la función en la capa de aplicación. |
REGEXP_INSTR(index,expr) |
Busca una posición de cadena (índice) para un patrón de expresión regular. | No | N/A | Solo se admite a partir de la versión 8 de MySQL. |
REVERSE(str) |
Devolver una cadena invertidaREVERSE('MySQL') = LQSyM |
Sí | REVERSE |
Equivalente a Oracle:REVERSE('MySQL') = LQSyM |
Funciones numéricas
Función de Oracle | Especificación o implementación de funciones de Oracle | Equivalente de MySQL | Función correspondiente de MySQL | Especificación o implementación de la función MySQL |
---|---|---|---|---|
ABS(n) |
Valor absoluto de n: ABS(-4.6) = 4.6 |
Sí | ABS |
Equivalente a Oracle:ABS(-4.6) = 4.6 |
CEIL(n) |
Devuelve el menor número entero que sea mayor o igual que n:CEIL(21.4) = 22 |
Sí | CEIL |
Equivalente a Oracle:CEIL(21.4) = 22 |
FLOOR(n) |
Devuelve el mayor número entero igual o inferior a n: FLOOR(-23.7) = -24 |
Sí | FLOOR |
Equivalente a Oracle:FLOOR(-23.7) = -24 |
MOD(m,n) |
Devuelve el resto de m dividido entre n:MOD(10, 3) = 1 |
Sí | MOD(m,n) |
Equivalente a Oracle:MOD(10,3) = 1 |
ROUND(m,n) |
Devuelve m redondeado a n decimales a la derecha del punto decimal:ROUND(1.39,1) = 1.4 |
Sí | ROUND |
Equivalente a Oracle:ROUND(1.39,1) = 1.4 |
TRUNC(n1, n2) |
Devuelve n1 truncado a n2 decimales:TRUNC(99.999) = 99 TRUNC(99.999,0) = 99 |
Parcialmente con un nombre de función diferente | TRUNCATE(n1, n2) |
La función TRUNCATE de MySQL debe aceptar un número de entrada y un número entero para especificar la cantidad de precisión a la derecha del punto decimal:TRUNCATE(99.999,0) = 99 |
Funciones de fecha y hora
Función de Oracle | Especificación o implementación de funciones de Oracle | Equivalente de MySQL | Función correspondiente de MySQL | Especificación o implementación de la función MySQL |
---|---|---|---|---|
SYSDATE |
Devuelve la fecha y la hora actuales definidas en el sistema operativo en el que reside el servidor de la base de datos:SELECT SYSDATE FROM DUAL = 31-JUL-2019 |
Parcialmente | SYSDATE() |
La función SYSDATE() de MySQL debe incluir paréntesis y devuelve un formato de fecha y hora diferente al de la función SYSDATE de Oracle:SELECT SYSDATE() FROM DUAL; = 2019-01-31 10:01:01.0 Tenga en cuenta que el formato de fecha y hora se puede cambiar a nivel de sesión. |
SYSTIMESTAMP |
Devuelve la fecha del sistema, incluidos los segundos fraccionarios y la zona horaria:SELECT SYSTIMESTAMP FROM DUAL = 01-JAN-19 07.37.11.622187000 AM +00:00 |
Parcialmente con un nombre de función diferente | CURRENT_TIMESTAMP |
MySQL devuelve un formato de fecha y hora diferente al de Oracle. Es necesario aplicar un formato de fecha (o usar otra función de fecha) para que coincida con el formato de fecha y hora original:SELECT CURRENT_TIMESTAMP FROM DUAL = 2019-01-31 06:55:07 |
LOCAL_TIMESTAMP |
Devuelve la fecha y la hora actuales en la zona horaria de la sesión como un valor de
tipo de datos TIMESTAMP :SELECT LOCAL_TIMESTAMP FROM DUAL = 01-JAN-19 10.01.10.123456 PM |
Parcialmente con un formato de fecha y hora diferente. | LOCAL_TIMESTAMP |
MySQL devuelve un formato de fecha y hora diferente al de Oracle. Es necesario aplicar un formato de fecha y hora (o usar otra función de fecha) para que coincida con el formato de fecha y hora original:SELECT LOCAL_TIMESTAMP FROM DUAL = 2019-01-01 10:01:01.0 |
CURRENT_DATE |
Devuelve la fecha actual en la zona horaria de la sesión:SELECT CURRENT_DATE FROM DUAL = 31-JAN-19 |
Parcialmente con un formato de fecha y hora diferente | CURRENT_DATE |
MySQL devuelve un formato de fecha y hora diferente al de Oracle. Es necesario aplicar un formato de fecha y hora (o usar otra función de fecha) para que coincida con el formato de fecha y hora original:SELECT CURRENT_DATE FROM DUAL = 2019-01-31 |
CURRENT_TIMESTAMP |
Devuelve la fecha y la hora actuales en la zona horaria de la sesión:SELECT CURRENT_TIMESTAMP FROM DUAL = 31-JAN-19 06.54.35.543146 AM +00:00 |
Parcialmente con un formato de fecha y hora diferente | CURRENT_TIMESTAMP |
MySQL devuelve un formato de fecha y hora diferente al de Oracle. Es necesario aplicar un formato de fecha y hora (o usar otra función de fecha) para que coincida con el formato de fecha y hora original:SELECT CURRENT_TIMESTAMP FROM DUAL = 2019-01-31 06:55:07 |
ADD_MONTHS |
Devuelve la fecha más los meses enteros:ADD_MONTHS(SYSDATE, 1) = 31-JAN-19 |
Parcialmente con un nombre de función diferente | ADDDATE |
Para conseguir la misma función, MySQL usa la ADDDATE función:ADDDATE(SYSDATE(), 1) = 2019-08-01 06:42:49.0 De forma predeterminada, MySQL devuelve una fecha, una hora, un intervalo o un formato distintos a los de Oracle. Es necesario aplicar el formato de fecha y hora (o una función de fecha diferente) para que coincida con el formato de fecha y hora original. |
EXTRACT (parte de la fecha) |
Devuelve el valor de un campo de fecha y hora especificado a partir de una expresión de fecha y hora o de intervalo:EXTRACT(YEAR FROM DATE '2019-01-31') = 2019 |
Sí | EXTRACT (parte de la fecha) |
Equivalente a Oracle:EXTRACT(YEAR FROM DATE '2019-01-31') = 2019 |
LAST_DAY |
Devuelve la fecha del último día del mes:LAST_DAY('01-JAN-2019') = 31-JAN-19 |
Parcialmente con un formato de fecha y hora diferente | LAST_DAY |
MySQL devuelve un formato de fecha y hora diferente al de Oracle. Es necesario aplicar un formato de fecha y hora (o usar otra función de fecha) para que coincida con el formato de fecha y hora original:LAST_DAY('2019-01-01') = 2019-01-31 |
MONTH_BETWEEN |
Devuelve el número de meses entre las fechas fecha1 y fecha2:MONTHS_BETWEEN( SYSDATE, SYSDATE-60) = 1.96 |
Parcialmente con un nombre de función diferente | PERIOD_DIFF(date1,date2) |
La función PERIOD_DIFF de MySQL devuelve la diferencia en meses como un número entero entre dos periodos (con el formato YYMM o YYYYMM ):PERIOD_DIFF( '201903', '201901') = 2 Para obtener los mismos valores que la función MONTH_BETWEEN de Oracle, se
necesitará una conversión más específica. |
TO_CHAR (fecha/hora) |
Convierte un tipo de datos de fecha, hora o marca de tiempo en un valor del tipo de datos VARCHAR2 con el formato especificado por el formato de fecha:TO_CHAR( SYSDATE,'DD-MM-YYYY HH24:MI:SS') = 01-01-2019 10:01:01 |
Parcialmente con un nombre de función diferente | DATE_FORMAT |
La función DATE_FORMAT de MySQL da formato a una fecha según lo especificado por una definición de formato de fecha:DATE_FORMAT( SYSDATE(),'%d-%m-%Y %H:%i:%s') = 01-01-2019 10:01:01 |
Funciones de codificación y decodificación
Función de Oracle | Especificación o implementación de funciones de Oracle | Equivalente de MySQL | Función correspondiente de MySQL | Especificación o implementación de la función MySQL |
---|---|---|---|---|
DECODE |
Compara una expresión con cada valor de búsqueda uno por uno mediante la función de una instrucción IF-THEN-ELSE . |
No | CASE |
Usa la instrucción CASE de MySQL para conseguir una función similar. |
DUMP |
Devuelve un valor VARCHAR2 que contiene el código del tipo de datos, la longitud en bytes y la representación interna de una expresión determinada. |
No | N/A | No es compatible. |
ORA_HASH |
Calcula un valor hash para una expresión determinada. | No | MD5/SHA |
Usa MD5 de MySQL para la suma de comprobación de 128 bits o la función SHA
para la suma de comprobación de 160 bits para generar valores hash. |
Funciones de conversión
Función de Oracle | Especificación o implementación de funciones de Oracle | Equivalente de MySQL | Función correspondiente de MySQL | Especificación o implementación de la función MySQL |
---|---|---|---|---|
CAST |
Convierte un tipo de datos integrado o un valor de tipo colección en otro tipo de datos integrado o valor de tipo colección: CAST('1' as int) + 1 = 2 |
Parcialmente | CAST |
La función CAST de MySQL es similar a la de Oracle, pero en
algunos casos debe ajustarse en función de si se requiere una conversión explícita o
implícita:CAST('1' AS SIGNED) + 1 = 2 |
CONVERT |
Convierte una cadena de caracteres de un conjunto de caracteres a otro: CONVERT('Ä Ê Í Õ Ø A B C D E ', 'US7ASCII', 'WE8ISO8859P1') = ?? ?? ?? A B C |
Parcialmente | CONVERT |
La función CONVERT de MySQL requiere algunos ajustes en la sintaxis y los parámetros para devolver los mismos resultados que Oracle:CONVERT('Ä Ê Í A B C ' USING utf8) = Ä Ê Í A B C |
TO_CHAR (cadena o número) |
La función convierte un número o una fecha en una cadena: TO_CHAR(22.73,'$99.9') = $22.7 |
No | FORMAT |
La función FORMAT de MySQL aplica el formato "#,###.##" a un número, lo redondea a un número determinado de decimales y, a continuación, devuelve el resultado como una cadena. Tiene una funcionalidad diferente a la de Oracle:CONCAT('$', FORMAT(22.73, 1)) = $22.7 |
TO_DATE |
La función TO_DATE de Oracle convierte una cadena en una fecha según el formato de fecha y hora específico de la fuente:TO_DATE( '2019/01/01', 'yyyy-mm-dd') = 01-JAN-2019 |
Parcialmente con un nombre de función y un formato de fecha y hora diferentes | STR_TO_DATE |
La función STR_TO_DATE de MySQL toma una cadena y devuelve una fecha especificada por el formato de fecha y hora:STR_TO_DATE( '2019/01/01', '%Y/%m/%d') = 2019-01-01 |
TO_NUMBER |
Convierte una expresión en un valor de tipo de datos NUMBER :TO_NUMBER('01234') = 1234 |
No | CAST |
Como alternativa, usa la función CAST de MySQL para devolver el mismo resultado que TO_NUMBER de Oracle:CAST('01234' as SIGNED) = 1234 |
Funciones SELECT condicionales
Función de Oracle | Especificación o implementación de funciones de Oracle | Equivalente de MySQL | Función correspondiente de MySQL | Especificación o implementación de la función MySQL |
---|---|---|---|---|
CASE |
La instrucción CASE elige entre una secuencia de condiciones y ejecuta una instrucción correspondiente con la siguiente sintaxis:CASE WHEN condition THEN result [WHEN ...] [ELSE result] END |
Sí | CASE |
Además de la función CASE , MySQL también admite el uso de IF/ELSE
gestión condicional dentro de la instrucción SELECT :CASE WHEN condition THEN result [WHEN ...] [ELSE result] END |
Funciones nulas
Función de Oracle | Especificación o implementación de funciones de Oracle | Equivalente de MySQL | Función correspondiente de MySQL | Especificación o implementación de la función MySQL |
---|---|---|---|---|
COALESCE |
Devuelve la primera expresión no nula de la lista de expresiones: COALESCE( null, '1', 'a') = a |
Sí | COALESCE |
Equivalente a Oracle:COALESCE( null, '1', 'a') = 1 |
NULLIF |
Compara expr1 y expr2m. Si son iguales, la función devuelve un valor nulo. Si no son iguales, la función devuelve expr1: NULLIF('1', '2') = a |
Sí | NULLIF |
Equivalente a Oracle:NULLIF('1', '2') = a |
NVL |
Sustituye el valor nulo (que se devuelve como un espacio en blanco) por una cadena en los resultados de una consulta:
NVL(null, 'a') = a |
No | IFNULL |
La función equivalente en MySQL sería la función IFNULL , que sustituye los valores nulos por una cadena determinada:IFNULL(null, 'a') = a |
NVL2 |
Determina el valor devuelto por una consulta en función de si una expresión especificada es nula o no. |
No | CASE |
La instrucción CASE elige entre una secuencia de condiciones y ejecuta una instrucción correspondiente: CASE WHEN condition THEN result [WHEN ...] [ELSE result] END |
Funciones de entorno e identificador
Función de Oracle | Especificación o implementación de funciones de Oracle | Equivalente de MySQL | Función correspondiente de MySQL | Especificación o implementación de la función MySQL |
---|---|---|---|---|
SYS_GUID |
Genera y devuelve un identificador único global (valor RAW) compuesto por 16 bytes:SELECT SYS_GUID() FROM DUAL = 8EFA4A31468B4C6DE05011AC0200009E |
No | REPLACE y UUID |
Para solucionar este problema, usa las funciones REPLACE y UUID de MySQL para simular la función SYS_GUID de Oracle:REPLACE( UUID(), '-', '') |
UID |
Devuelve un número entero que identifica de forma única al usuario de la sesión (el usuario que ha iniciado sesión): SELECT UID FROM DUAL = 43 |
No | N/A | N/A |
USER |
Devuelve el nombre de usuario de la sesión actual:SELECT USER FROM DUAL = UserName |
Parcialmente | USER + INSTR + SUBSTR |
La función USER de MySQL devuelve el nombre de usuario junto con el servidor de conexión (root@IP ). Para obtener solo el nombre de usuario, utiliza funciones complementarias:SELECT SUBSTR(USER(), 1, INSTR(USER(), '@') -1) FROM DUAL = root |
USERENV |
Devuelve información sobre la sesión del usuario actual con la configuración de parámetros actual:SELECT USERENV('LANGUAGE') FROM DUAL = ENGLISH_AMERICA.AL32UTF8 |
No | SHOW SESSION VARIABLES |
Usa la instrucción SHOW SESSION VARIABLES de MySQL para ver la configuración de la sesión actual:SHOW SESSION VARIABLES LIKE '%collation%'; = utf8_general_ci |
ROWID |
El servidor de Oracle asigna a cada fila de cada tabla un ROWID único para identificar la fila en la tabla. ROWID es la dirección de la fila que contiene el número del objeto de datos, el bloque de datos de la fila, la posición de la fila y el archivo de datos. |
No | N/A | Si es posible, intenta emular la misma función con otras funciones de MySQL. |
ROWNUM |
Devuelve un número que representa el orden en el que Oracle selecciona una fila de una tabla o de tablas combinadas. | No | N/A | Si es posible, intenta emular la misma función con otras funciones o variables de sesión de MySQL. |
Funciones de agregación (grupo)
Función de Oracle | Especificación o implementación de la función Oracle |
Equivalente de MySQL |
Función correspondiente de MySQL | Especificación o implementación de la función MySQL |
---|---|---|---|---|
AVG |
Devuelve el valor medio de una columna o una expresión. | Sí | AVG |
Equivalente a Oracle |
COUNT |
Devuelve el número de filas devueltas por una consulta. | Sí | COUNT |
Equivalente a Oracle |
COUNT (DISTINCT) |
Devuelve el número de valores únicos de la columna o expresión. | Sí | COUNT (DISTINCT) |
Equivalente a Oracle |
MAX |
Devuelve el valor máximo de una columna o una expresión. | Sí | MAX |
Equivalente a Oracle |
MIN |
Devuelve el valor mínimo de una columna o una expresión. | Sí | MIN |
Equivalente a Oracle |
SUM |
Devuelve la suma del valor de una columna o una expresión. | Sí | SUM |
Equivalente a Oracle |
LISTAGG |
Muestra los datos de cada grupo en una sola fila especificada en la cláusula ORDER BY concatenando los valores de la columna de medida:SELECT LISTAGG( DEPARTMENT_NAME, ', ') WITHIN GROUP (ORDER BY DEPARTMENT_NAME) DEPT FROM DEPARTMENTS; |
No | GROUP_CONCAT |
Usa la función GROUP_CONCAT de MySQL para obtener resultados similares a los de Oracle.
Ten en cuenta que la sintaxis es diferente en algunos casos:SELECT GROUP_CONCAT( DEPARTMENT_NAME ORDER BY DEPARTMENT_NAME SEPARATOR ', ') DEPT FROM DEPARTMENTS; |
Obtención de Oracle 12c
Función de Oracle | Especificación o implementación de la función Oracle |
Equivalente de MySQL |
Función correspondiente de MySQL | Especificación o implementación de la función MySQL |
---|---|---|---|---|
FETCH |
Obtiene filas de datos del conjunto de resultados de una consulta de varias filas: SELECT * FROM EMPLOYEES FETCH FIRST 10 ROWS ONLY; |
No | LIMIT | Usa la cláusula LIMIT
de MySQL para obtener solo un conjunto específico de registros:SELECT * FROM EMPLOYEES LIMIT 10; |
Filtrado básico, operadores y subconsultas
Durante la conversión, el filtrado básico, las funciones de operador y las subconsultas son relativamente sencillos y requieren poco o ningún esfuerzo adicional.
Notas de conversión
Examina y corrige los formatos de fecha, ya que los formatos de Oracle y MySQL devuelven resultados predeterminados diferentes:
- La función
SYSDATE
de Oracle devuelve01-AUG-19
de forma predeterminada. - La función
SYSDATE()
de MySQL devuelve2019-08-01 12:04:05
de forma predeterminada. - Los formatos de fecha y hora se pueden definir con las funciones de MySQL
[DATE_FORMAT](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format)
o[STR_TO_DATE](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_str-to-date)
.
Función o subconsulta de Oracle | Equivalente de MySQL | Función o subconsulta correspondiente de MySQL | Especificación o implementación de la función MySQL |
---|---|---|---|
EXISTS/NOT EXISTS |
Sí | EXISTS/NOT EXISTS |
SELECT * FROM DEPARTMENTS D WHERE EXISTS (SELECT 1 FROM EMPLOYEES E WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID); |
IN/NOT IN |
Sí | IN/NOT IN |
SELECT * FROM DEPARTMENTS D WHERE DEPARTMENT_ID IN (SELECT DEPARTMENT_ID FROM EMPLOYEES E); |
LIKE/NOT LIKE |
Sí | LIKE/NOT LIKE |
SELECT * FROM EMPLOYEES WHERE FIRST_NAME LIKE '_e_n%'; |
BETWEEN/NOT BETWEEN |
Sí | BETWEEN/NOT BETWEEN |
SELECT * FROM EMPLOYEES WHERE EXTRACT(YEAR FROM HIRE_DATE) NOT BETWEEN 2001 and 2004; |
AND/OR |
Sí | AND/OR |
SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID IN(100, 101) AND (SALARY >= 1000 OR HIRE_DATE <= '2006-02-05'); |
SubQuery |
Sí | SubQuery |
MySQL admite subconsultas en el nivel SELECT para las instrucciones JOIN y para filtrar en las cláusulas WHERE/AND :-- SELECT SubQuery SELECT D.DEPARTMENT_NAME, (SELECT AVG(SALARY) AS AVG_SAL FROM EMPLOYEES E WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID) AVG_SAL FROM DEPARTMENTS D; |
Operadores | Sí | Operadores | MySQL admite todos los operadores básicos:> | >= | < | <= | = | <> | != |
Funciones analíticas (o funciones de ventana y de clasificación)
Las funciones analíticas de Oracle amplían la funcionalidad de las funciones analíticas de SQL estándar al proporcionar funciones para calcular valores agregados basados en un grupo de filas. Estas funciones se pueden aplicar a conjuntos de resultados particionados lógicamente dentro del ámbito de una sola expresión de consulta. Se suelen usar en combinación con informes y analíticas de inteligencia empresarial, con el potencial de mejorar el rendimiento de las consultas como alternativa para conseguir el mismo resultado con un código SQL no analítico más complejo.
Notas de conversión
- La versión 5.7 de MySQL no proporciona funciones analíticas para admitir una conversión sencilla de instrucciones SQL. Sin embargo, esta función se añadió parcialmente en MySQL 8, por lo que la conversión de funciones analíticas es un aspecto que se debe tener en cuenta y que probablemente requiera un esfuerzo manual en el proceso de migración.
- Otra solución opcional es reescribir el código para eliminar el uso de funciones analíticas, volver a soluciones de código SQL más tradicionales o mover esta lógica a una capa de aplicación.
En la siguiente tabla se enumeran las funciones analíticas comunes de Oracle.
Familia de funciones | Funciones relacionadas | Compatible con MySQL 5.7 |
---|---|---|
Analíticas y de clasificación | RANK AVERAGE_RANK DENSE_RANK RANK ROW_NUMBER PERCENT_RANK CUME_DIST NTILE FIRST_VALUE LAST_VALUE OVER (PARTITION BY...) |
No |
Jerárquico | CONNECT BY HIER_ANCESTOR HIER_CHILD_COUNT HIER_DEPTH HIER_LEVEL HIER_ORDER HIER_PARENT HIER_TOP |
No |
Retraso | LAG LAG_VARIANCE LAG_VARIANCE_PERCENT LEAD LEAD_VARIANCE LEAD_VARIANCE_PERCENT |
No |
Expresión de tabla común (CTE)
Las CTEs proporcionan una forma de implementar la lógica del código secuencial para reutilizar el código SQL
que puede ser demasiado complejo o no eficiente para un uso múltiple. Las CTEs se pueden nombrar y, a continuación, usar varias veces en diferentes partes de una instrucción SQL mediante la cláusula WITH
.
Notas de conversión
- La versión 5.7 de MySQL no admite CTEs, pero la versión 8 de MySQL sí.
- Para obtener una solución alternativa, usa tablas derivadas o subconsultas, o reescribe la instrucción SQL para eliminar la función CTE.
Ejemplos
Oracle |
---|
WITH DEPT_COUNT (DEPARTMENT_ID, DEPT_COUNT) AS (SELECT DEPARTMENT_ID, COUNT(*) FROM EMPLOYEES GROUP BY DEPARTMENT_ID) |
MySQL |
SELECT * FROM ( SELECT CONCAT(E.FIRST_NAME, ' ', E.LAST_NAME) AS EMP_NAME, (SELECT COUNT(*) FROM EMPLOYEES D WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID GROUP BY DEPARTMENT_ID) AS EMP_DEPT_COUNT FROM EMPLOYEES E ORDER BY 2 DESC) TBL WHERE EMP_DEPT_COUNT IS NOT NULL; |
Instrucción MERGE
La instrucción MERGE
(o UPSERT
) permite especificar instrucciones SQL únicas que realizan operaciones de DML de forma condicional en una operación MERGE
, en lugar de una sola operación de DML que se ejecuta por separado. Selecciona registros de la tabla de origen y, a continuación, al especificar una estructura lógica, realiza automáticamente varias operaciones DML en la tabla de destino. Esta función te ayuda a evitar el uso de varias inserciones, actualizaciones o eliminaciones. Ten en cuenta que MERGE
es una instrucción determinista, lo que significa que, una vez que una fila se ha procesado con la instrucción MERGE
, no se puede volver a procesar con la misma instrucción MERGE
.
Notas de conversión
La versión 5.7 de MySQL no admite la función MERGE
, a diferencia de Oracle. Para simular parcialmente la función MERGE
, MySQL proporciona las instrucciones REPLACE
y INSERT… ON DUPLICATE KEY UPDATE
:
REPLACE
: funciona de la misma forma que una instrucciónINSERT
, excepto que, si una fila antigua de la tabla tiene el mismo valor que una fila nueva para un índicePRIMARY KEY
oUNIQUE
, la fila antigua se elimina antes de insertar la nueva.INSERT… ON DUPLICATE KEY UPDATE
: Si una fila insertada provoca un valor duplicado en un índicePRIMARY KEY
oUNIQUE
, se produce unaUPDATE
de la fila antigua para eliminar la excepción de clave duplicada. Por ejemplo:INSERT INTO tbl (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1; UPDATE tbl SET c=c+1 WHERE a=1;
Otra solución sería convertir la función MERGE
en un procedimiento almacenado para gestionar las operaciones de DML, usando los comandos INSERT
, UPDATE
y DELETE
con gestión de excepciones y duplicaciones.
Pistas de instrucciones SQL
Oracle ofrece una gran colección de sugerencias de consultas SQL que permiten a los usuarios influir en el comportamiento del optimizador y en sus decisiones, con el objetivo de producir planes de ejecución de consultas más eficientes. Oracle admite más de 60 sugerencias de bases de datos diferentes. MySQL proporciona un conjunto limitado de sugerencias de consulta.
En general, la versión 5.7 de MySQL admite dos tipos de sugerencias de consulta: OPTIMIZER
HINTS
y INDEX HINTS
.
Sugerencias del optimizador de MySQL te permiten controlar el comportamiento del optimizador en instrucciones SQL concretas. Por ejemplo:
SELECT /*+ NO_RANGE_OPTIMIZATION(tbl PRIMARY, col1_idx) */ col1 FROM tbl;
Sugerencias de optimización disponibles en MySQL versión 5.7
Nombre de la pista | Resumen de las pistas | Permisos aplicables |
---|---|---|
BKA, NO_BKA |
Afecta al procesamiento de la unión de acceso de clave por lotes | Bloque de consulta, tabla |
BNL, NO_BNL |
Afecta al procesamiento de combinaciones de bucles anidados de bloques. | Bloque de consulta, tabla |
MAX_EXECUTION_TIME |
Limita el tiempo de ejecución de las instrucciones. | Global |
MRR, NO_MRR |
Afecta a la optimización de lectura de varios intervalos | Tabla, índice |
NO_ICP |
Afecta a la optimización de la inserción de condiciones de índice | Tabla, índice |
NO_RANGE_OPTIMIZATION |
Afecta a la optimización del intervalo | Tabla, índice |
QB_NAME |
Asigna un nombre al bloque de consulta. | Bloque de consulta |
SEMIJOIN, NO_SEMIJOIN |
Afecta a las estrategias de combinación semi-join | Bloque de consulta |
SUBQUERY |
Afecta a la materialización y a las estrategias de subconsultas de IN a EXISTS . |
Bloque de consulta |
Las sugerencias de índice de MySQL proporcionan al optimizador información sobre cómo elegir los índices durante el procesamiento de las consultas. Las palabras clave USE
, FORCE
o IGNORE
se usan para controlar el proceso de uso del índice del optimizador. Por ejemplo:
SELECT * FROM tbl USE INDEX (col1_index, col2_index);
-- OR
SELECT * FROM tbl IGNORE INDEX (col1_index, col2_index);
Notas de conversión
Debido a las diferencias fundamentales entre los optimizadores de Oracle y MySQL, y a que las sugerencias de consulta de Oracle y MySQL apenas se solapan, te recomendamos que conviertas cualquier instrucción SQL de Oracle que contenga sugerencias de consulta no especificadas en la base de datos MySQL de destino.
Ajusta el rendimiento de MySQL con herramientas de MySQL (por ejemplo, Workbench de MySQL para obtener paneles de rendimiento en tiempo real) y funciones como examinar consultas mediante planes de ejecución y ajustar los parámetros de la instancia o de la sesión según el caso práctico.
Planes de ejecución
El objetivo principal de los planes de ejecución es ofrecer una visión interna de las decisiones que toma el optimizador de consultas para acceder a los datos de la base de datos. El optimizador de consultas genera planes de ejecución para las instrucciones SELECT
, INSERT
, UPDATE
y DELETE
de los usuarios de la base de datos, y también permite a los administradores tener una mejor visión de las consultas y las operaciones de DML específicas. Son especialmente útiles cuando necesitas ajustar el rendimiento de las consultas; por ejemplo, para determinar el rendimiento de los índices o para determinar si faltan índices que deben crearse.
Los planes de ejecución pueden verse afectados por los volúmenes de datos, las estadísticas de datos y los parámetros de instancia (parámetros globales o de sesión).
Consideraciones sobre la conversión
Los planes de ejecución no son objetos de base de datos que deban migrarse, sino una herramienta para analizar las diferencias de rendimiento entre Oracle y MySQL al ejecutar la misma instrucción en conjuntos de datos idénticos.
MySQL no admite la misma sintaxis, funcionalidad ni salida del plan de ejecución que Oracle.
Ejemplos
Plan de ejecución de Oracle |
---|
SQL> EXPLAIN PLAN FOR SELECT * FROM EMPLOYEES WHERE EMPLOYEE_ID = 105; |
Plan de ejecución de MySQL |
mysql> EXPLAIN SELECT * FROM EMPLOYEES WHERE EMPLOYEE_ID = 105; |
Procedimientos almacenados, funciones y activadores
PL/SQL es el lenguaje procedimental ampliado de Oracle que se usa para crear, almacenar y aplicar soluciones basadas en código en la base de datos. En general, los procedimientos almacenados y las funciones de las bases de datos son elementos de código que constan de ANSI SQL y un lenguaje procedimental ampliado de SQL, como PL/SQL para Oracle, PL/pgSQL para PostgreSQL y el lenguaje procedimental de MySQL para MySQL. MySQL usa el mismo nombre que la base de datos para su propio lenguaje de procedimiento ampliado.
El objetivo de estos procedimientos y funciones almacenados es ofrecer soluciones para requisitos que se adapten mejor a la ejecución desde la base de datos y no desde la aplicación (por ejemplo, rendimiento, compatibilidad y seguridad). Aunque tanto los procedimientos almacenados como las funciones usan PL/SQL, los procedimientos almacenados se usan principalmente para realizar operaciones DDL o DML, y las funciones se usan principalmente para realizar cálculos y devolver resultados específicos.
PL/SQL a lenguaje de procedimientos de MySQL
Desde el punto de vista de la migración de código de Oracle PL/SQL a MySQL, la implementación de procedimientos de MySQL es diferente a la de Oracle. Por lo tanto, es necesario migrar el código para convertir la funcionalidad de PL/SQL de Oracle en procedimientos almacenados y funciones de MySQL. Además, MySQL no admite los paquetes ni los cuerpos de paquetes de Oracle, por lo que, cuando conviertas código, convierte estos elementos (o analízalos) en unidades individuales de código de MySQL. Ten en cuenta que los procedimientos almacenados y las funciones de MySQL también se denominan rutinas.
Propietario del objeto de código
En Oracle, el propietario de un procedimiento o una función almacenados es un usuario específico. En MySQL, el propietario es un esquema específico (creado en una base de datos por un usuario de la base de datos).
Privilegios y seguridad de los objetos de código
En Oracle, para crear un procedimiento o una función almacenados, el usuario debe tener el privilegio de sistema CREATE PROCEDURE
(para crear procedimientos o funciones en otros usuarios, los usuarios de la base de datos deben tener el privilegio CREATE
ANY PROCEDURE
). Para ejecutar un procedimiento almacenado o una función, los usuarios de la base de datos deben tener el privilegio EXECUTE
.
En MySQL, para crear un elemento de código, el usuario debe tener el privilegio CREATE
ROUTINE
y el privilegio EXECUTE
para ejecutarlo. La cláusula DEFINER
de MySQL define el creador del objeto de código y el usuario debe tener los
privilegios adecuados, como CREATE ROUTINE
.
Sintaxis de procedimientos y funciones almacenados de MySQL
En el siguiente ejemplo se muestra la sintaxis del procedimiento almacenado y la función de MySQL:
CREATE
[DEFINER = user]
PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body
CREATE
[DEFINER = user]
FUNCTION sp_name ([func_parameter[,...]])
RETURNS type
[characteristic ...] routine_body
proc_parameter:
[ IN | OUT | INOUT ] param_name type
func_parameter:
param_name type
type:
Any valid MySQL data type
characteristic:
COMMENT 'string'
| LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
routine_body:
Valid SQL routine statement