Este documento es parte de una serie que proporciona información clave y orientación relacionada con la planificación y la realización de migraciones de bases de datos de Oracle® 11g o 12c a instancias de segunda generación con versión 5.7 de Cloud SQL para MySQL. En la serie, se incluyen las siguientes partes:
- Migra usuarios de Oracle a Cloud SQL para MySQL: terminología y funcionalidad
- Migra usuarios de Oracle a Cloud SQL para MySQL: tipos de datos, usuarios y tablas
- Migra usuarios de Oracle a Cloud SQL para MySQL: consultas, procedimientos almacenados, funciones y activadores (este documento)
- Migra usuarios de Oracle a Cloud SQL para MySQL: seguridad, operaciones, supervisión y registro
Consultas
Oracle y Cloud SQL para MySQL admiten el estándar ANSI SQL. En general, es sencillo migrar instrucciones de SQL mediante el uso de elementos de sintaxis básicos (por ejemplo, sin especificar ninguna función escalar o cualquier otra característica extendida de Oracle). En la siguiente sección, se analizan los elementos de consulta comunes de Oracle y sus equivalentes de Cloud SQL para MySQL.
Sintaxis básica SELECT y FROM
Nombre de sintaxis o nombre de la característica de Oracle | Implementación o descripción general de Oracle | Compatibilidad con MySQL | Solución alternativa o correspondiente de MySQL |
---|---|---|---|
Sintaxis básica de SQL para la recuperación de datos | SELECT FROM WHERE GROUP BY HAVING ORDER BY |
Sí | SELECT FROM WHERE GROUP BY HAVING ORDER BY |
SELECT para 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 |
Distinción entre mayúsculas y minúsculas del nombre de la tabla |
Sin distinción entre mayúsculas y minúsculas (por ejemplo, el nombre de la tabla puede ser orders o bien ORDERS ). |
No | Distingue entre mayúsculas y minúsculas según el nombre de la tabla definida (por ejemplo, el nombre de la tabla solo puede ser orders o bien ORDERS ). |
Puedes leer más detalles sobre la sintaxis SELECT
de MySQL.
- Vistas en línea
- Las vistas en línea (también conocidas como tablas derivadas) son declaraciones
SELECT
, que se ubican en la cláusulaFROM
y se usan como una subconsulta. - Las vistas en línea pueden ayudar a simplificar las consultas complejas, ya que quitan los cálculos compuestos, o eliminan las operaciones de unión, a la vez que condensan varias consultas separadas en una sola consulta simplificada.
- Nota de conversión: Las vistas en línea de Oracle no requieren el uso de alias, mientras que MySQL sí requiere alias específicos para cada vista en línea.
- Las vistas en línea (también conocidas como tablas derivadas) son declaraciones
En la siguiente tabla, se presenta un ejemplo de conversión de Oracle a MySQL, como una vista en línea.
Oracle 11g/12c |
---|
SQL> SELECT FIRST_NAME, DEPARTMENT_ID, SALARY, DATE_COL FROM EMPLOYEES, (SELECT SYSDATE AS DATE_COL FROM DUAL); El resultado es similar al 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 en línea:mysql> SELECT FIRST_NAME, DEPARTMENT_ID, SALARY, DATE_COL FROM EMPLOYEES, (SELECT SYSDATE() AS DATE_COL FROM DUAL); Agregar un alias a la vista en línea: mysql> SELECT FIRST_NAME, DEPARTMENT_ID, SALARY, DATE_COL FROM EMPLOYEES, (SELECT SYSDATE() AS DATE_COL FROM DUAL) AS A1; El resultado es similar al 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
Las declaraciones JOIN
de Oracle son compatibles con las declaraciones JOIN
de MySQL, excepto la cláusula FULL JOIN
. Además, las declaraciones JOIN
de MySQL admiten el uso de sintaxis alternativa, como la cláusula USING
, la cláusula WHERE
en lugar de la cláusula ON
y el uso de SUBQUERY
en la declaración JOIN
.
En la siguiente tabla, se presenta un ejemplo de conversión JOIN.
Tipo de JOIN de Oracle | Compatible con 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 una solución alternativa, considera usar UNION con declaraciones 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 declaracionesSELECT
y elimina los registros duplicados.UNION ALL
: Adjunta los conjuntos de resultados de dos o más declaracionesSELECT
sin eliminar los registros duplicados.INTERSECT
: Muestra la intersección de dos o más declaracionesSELECT
solo si existe un registro en ambos conjuntos de datos.MINUS
: Compara dos o más declaracionesSELECT
y muestra solo filas distintas de la primera consulta que no muestran las otras declaraciones.
Notas de la conversión
Cuando conviertas las funciones INTERSECT
y MINUS
de Oracle en MySQL, usa las declaraciones JOIN
, IN
y EXISTS
como solución alternativa.
Ejemplos
Función de Oracle | Implementación de Oracle | Compatibilidad con MySQL | Solución alternativa o correspondiente 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 lista extensa de funciones escalares (de una sola fila) y de agregación. Algunas de las funciones de MySQL son similares a sus contrapartes de Oracle (en cuanto al nombre y la funcionalidad, o tienen un nombre diferente, pero una funcionalidad similar). Aunque las funciones de MySQL pueden tener nombres idénticos a sus contrapartes de Oracle, pueden exhibir una funcionalidad diferente.
En las siguientes tablas, se describe en qué casos son equivalentes Oracle y MySQL por nombre y funcionalidad (especificado por "Sí") y en qué casos se recomienda una conversión (todos los casos distintos de "Sí").
Funciones de caracteres
Función de Oracle | Implementación o especificación de la función de Oracle | Equivalente de MySQL | Función correspondiente de MySQL | Implementación o especificación de funciones de MySQL |
---|---|---|---|---|
CONCAT(str1,str2) |
Muestra str1 concatenado con str2:CONCAT('A', 1) = A1 |
Sí | CONCAT |
Equivalente a Oracle:CONCAT('A', 1) = A1 |
LOWER/UPPER |
Muestra char, con todas las letras en minúscula o mayúscula:LOWER('SQL') = sql |
Sí | LOWER/UPPER |
Equivalente a Oracle:LOWER('SQL') = sql |
LPAD/RPAD(expr1,n,expr2) |
Muestra expr1, con relleno izquierdo o derecho con n caracteres, con la secuencia de caracteres en expr2:LPAD('A',3,'*') = **A |
Sí | LPAD/RPAD |
Equivalente a Oracle:LPAD('A',3,'*') = **A |
SUBSTR(char,p,n) |
Muestra una parte de char, que comienza en la posición del carácter p, con una longitud de la substring de n caracteres:SUBSTR('MySQL', 3, 3) = SQL |
Sí | SUBSTR(char,p,n) |
Equivalente a Oracle:SUBSTR('MySQL', 3, 3) = SQL |
INSTR(index,str) |
Muestra la posición (índice) de la string str:INSTR('MySQL', 'y') = 2 |
Sí | INSTR |
Equivalente a Oracle:INSTR('MySQL', 'y') = 2 |
REPLACE(char,str1,str2) |
Muestra char con cada ocurrencia de una string de búsqueda reemplazada por una string de reemplazo: REPLACE('ORADB', 'ORA', 'MySQL') |
Sí | REPLACE(char,str1,str2) |
Equivalente a Oracle:REPLACE('ORADB', 'ORA', 'MySQL') |
TRIM(str) |
Recorta los caracteres iniciales o finales (o ambos) de una string:TRIM(both '-' FROM '-MySQL-') = MySQL |
Sí | TRIM(str) |
Equivalente a Oracle:TRIM(both '-' FROM '-MySQL-') = MySQL |
LTRIM/RTRIM(str) |
Quita del extremo izquierdo o derecho de la string todos los caracteres que aparecen en la búsqueda:LTRIM(' MySQL', ' ') = MySQL |
De forma parcial | LTRIM/RTRIM(str) |
Función R/LTRIM de Oracle, excepto un reemplazo de parámetro (espacio en blanco o string). R/LTRIM de MySQL solo elimina los espacios en blanco y acepta solo la string de entrada:LTRIM(' MySQL') = MySQL |
ASCII(char) |
Muestra la representación decimal en el grupo 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) |
Muestra el valor del código ASCII, que es un valor numérico entre 0 y 225, para un carácter:CHR(65) = A |
De forma parcial con un nombre de función diferente | CHAR(char) |
MySQL usa la función CHAR para la misma funcionalidad; por lo tanto, debes modificar el nombre de una función:CHAR(65) = A |
LENGTH(str) |
Muestra la longitud de una string determinada:LENGTH ('MySQL') = 5 |
Sí | LENGTH(str) |
Equivalente a Oracle:LENGTH('MySQL') = 5 |
REGEXP_REPLACE(str1,expr,str2) |
Busca un patrón de expresión regular en una string:REGEXP_REPLACE('John', '[hn].', '1') = Jo1 |
No | No disponible | Solo se admite desde la versión 8 de MySQL. Como solución alternativa, usa la función REPLACE , si es posible, o realiza la conversión a la capa de la aplicación. |
REGEXP_SUBSTR(str,expr) |
Extiende la funcionalidad de la función SUBSTR mediante la búsqueda de un patrón de expresión regular en una string:REGEXP_SUBSTR('https://console.cloud.google.com/sql/instances','https://([[:alnum:]]+\.?){3,4}/?') = https://console.cloud.google.com/ |
No | No disponible | Solo compatible con la versión 8 de MySQL. Como solución alternativa, usa la función SUBSTR , si es posible, o convierte la funcionalidad en la capa de la aplicación. |
REGEXP_COUNT(str,expr) |
Muestra la cantidad de veces que se produce un patrón en una string de origen. | No | No disponible | Como una solución alternativa, convierte la funcionalidad en la capa de la aplicación. |
REGEXP_INSTR(index,expr) |
Busca una posición de string (índice) para un patrón de expresión regular. | No | No disponible | Solo compatible con la versión 8 de MySQL. |
REVERSE(str) |
Muestra una string invertidaREVERSE('MySQL') = LQSyM |
Sí | REVERSE |
Equivalente a Oracle:REVERSE('MySQL') = LQSyM |
Funciones numéricas
Función de Oracle | Implementación o especificación de la función de Oracle | Equivalente de MySQL | Función correspondiente de MySQL | Implementación o especificación de funciones de MySQL |
---|---|---|---|---|
ABS(n) |
Valor absoluto de n:ABS(-4.6) = 4.6 |
Sí | ABS |
Equivalente a Oracle:ABS(-4.6) = 4.6 |
CEIL(n) |
Muestra el número entero más pequeño mayor o igual que n:CEIL(21.4) = 22 |
Sí | CEIL |
Equivalente a Oracle:CEIL(21.4) = 22 |
FLOOR(n) |
Muestra el número entero más grande menor o igual que n: FLOOR(-23.7) = -24 |
Sí | FLOOR |
Equivalente a Oracle:FLOOR(-23.7) = -24 |
MOD(m,n) |
Muestra el resto de la división de m por n:MOD(10, 3) = 1 |
Sí | MOD(m,n) |
Equivalente a Oracle:MOD(10,3) = 1 |
ROUND(m,n) |
Muestra m redondeado a n números enteros 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) |
Muestra n1 truncado en n2 decimales:TRUNC(99.999) = 99 TRUNC(99.999,0) = 99 |
De forma parcial 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 | Implementación o especificación de la función de Oracle | Equivalente de MySQL | Función correspondiente de MySQL | Implementación o especificación de funciones de MySQL |
---|---|---|---|---|
SYSDATE |
Muestra la fecha y hora actuales establecidas para el sistema operativo en el que reside el servidor de la base de datos:SELECT SYSDATE FROM DUAL = 31-JUL-2019 |
De forma parcial | SYSDATE() |
El SYSDATE() de MySQL debe incluir paréntesis y muestra 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 Ten en cuenta que el formato de fecha y hora se puede cambiar a nivel de la sesión |
SYSTIMESTAMP |
Muestra la fecha del sistema, incluidos los segundos y la zona horaria:SELECT SYSTIMESTAMP FROM DUAL = 01-JAN-19 07.37.11.622187000 AM +00:00 |
De forma parcial con un nombre de función diferente | CURRENT_TIMESTAMP |
MySQL muestra un formato de fecha y hora diferente al de Oracle. Se requiere un formato de fecha (o una función de fecha diferente) para que coincida con el formato de fecha y hora original:SELECT CURRENT_TIMESTAMP FROM DUAL = 2019-01-31 06:55:07 |
LOCAL_TIMESTAMP |
Muestra la fecha y hora actuales en la zona horaria de la sesión en un valor de tipo de datos TIMESTAMP :SELECT LOCAL_TIMESTAMP FROM DUAL = 01-JAN-19 10.01.10.123456 PM |
De forma parcial con un formato de fecha y hora diferente. | LOCAL_TIMESTAMP |
MySQL muestra un formato de fecha y hora diferente al de Oracle. El formato de fecha y hora es obligatorio (o una función de fecha diferente) para coincidir con el formato de fecha y hora original:SELECT LOCAL_TIMESTAMP FROM DUAL = 2019-01-01 10:01:01.0 |
CURRENT_DATE |
Muestra la fecha actual en la zona horaria de la sesión:SELECT CURRENT_DATE FROM DUAL = 31-JAN-19 |
De forma parcial con un formato de fecha y hora diferente | CURRENT_DATE |
MySQL muestra un formato de fecha y hora diferente al de Oracle. El formato de fecha y hora es obligatorio (o una función de fecha diferente) para coincidir con el formato de fecha y hora original:SELECT CURRENT_DATE FROM DUAL = 2019-01-31 |
CURRENT_TIMESTAMP |
Muestra la fecha y 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 |
De forma parcial con un formato de fecha y hora diferente | CURRENT_TIMESTAMP |
MySQL muestra un formato de fecha y hora diferente al de Oracle. El formato de fecha y hora es obligatorio (o una función de fecha diferente) para coincidir con el formato de fecha y hora original:SELECT CURRENT_TIMESTAMP FROM DUAL = 2019-01-31 06:55:07 |
ADD_MONTHS |
Muestra la fecha y los meses en números enteros:ADD_MONTHS(SYSDATE, 1) = 31-JAN-19 |
De forma parcial con un nombre de función diferente | ADDDATE |
Para lograr la misma funcionalidad, MySQL usa la función ADDDATE :ADDDATE(SYSDATE(), 1) = 2019-08-01 06:42:49.0 De forma predeterminada, MySQL muestra una fecha/hora y un rango/formato diferentes a los de Oracle. El formato de fecha y hora es obligatorio (o una función de fecha diferente) para coincidir con el formato de fecha y hora original. |
EXTRACT (parte de la fecha) |
Muestra el valor de un campo de fecha/hora especificado de una expresión de fecha/hora o 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 |
Muestra la fecha del último día del mes:LAST_DAY('01-JAN-2019') = 31-JAN-19 |
De forma parcial con un formato de fecha y hora diferente | LAST_DAY |
MySQL muestra un formato de fecha y hora diferente al de Oracle. El formato de fecha y hora es obligatorio (o una función de fecha diferente) para coincidir con el formato de fecha y hora original:LAST_DAY('2019-01-01') = 2019-01-31 |
MONTH_BETWEEN |
Muestra el número de meses entre las fechas date1 y date2:MONTHS_BETWEEN( SYSDATE, SYSDATE-60) = 1.96 |
De forma parcial con un nombre de función diferente | PERIOD_DIFF(date1,date2) |
La función PERIOD_DIFF de MySQL muestra la diferencia en meses como un número entero entre dos períodos (con formato YYMM o YYYYMM ):PERIOD_DIFF( '201903', '201901') = 2 Para lograr los mismos valores que la función MONTH_BETWEEN de Oracle, se requerirá una conversión más específica |
TO_CHAR (Fecha y hora) |
Convierte un tipo de datos de fecha/hora o marca de tiempo en un valor de tipo de datos VARCHAR2 en el formato especificado por el formato de fecha:TO_CHAR( SYSDATE,'DD-MM-YYYY HH24:MI:SS') = 01-01-2019 10:01:01 |
De forma parcial con un nombre de función diferente | DATE_FORMAT |
La función DATE_FORMAT de MySQL da formato a una fecha según lo especifica 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 | Implementación o especificación de la función de Oracle | Equivalente de MySQL | Función correspondiente de MySQL | Implementación o especificación de funciones de MySQL |
---|---|---|---|---|
DECODE |
Compara la expresión con cada valor de búsqueda, uno por uno, mediante la funcionalidad de una declaración IF-THEN-ELSE . |
No | CASE |
Usa la declaración CASE de MySQL para lograr una funcionalidad similar. |
DUMP |
Muestra un valor VARCHAR2 que contiene el código de tipo de datos, la longitud en bytes y la representación interna para una expresión determinada. |
No | No disponible | No compatible. |
ORA_HASH |
Calcula un valor de hash para una expresión determinada. | No | MD5/SHA |
Usa MD5 de MySQL para la suma de verificación de 128 bits o la función SHA para la suma de verificación de 160 bits a fin de generar valores de hash |
Funciones de conversión
Función de Oracle | Implementación o especificación de la función de Oracle | Equivalente de MySQL | Función correspondiente de MySQL | Implementación o especificación de funciones de MySQL |
---|---|---|---|---|
CAST |
Convierte un tipo de datos integrado o un valor de tipo de colección en otro tipo de datos integrado o un valor de tipo de colección:CAST('1' as int) + 1 = 2 |
De forma parcial | CAST |
La función CAST de MySQL es similar a la funcionalidad de Oracle, pero en ciertos casos debe ajustarse según si se requiere una conversión explícita o implícita:CAST('1' AS SIGNED) + 1 = 2 |
CONVERT |
Convierte una string de caracteres de un conjunto de caracteres en otro:CONVERT('Ä Ê Í Õ Ø A B C D E ', 'US7ASCII', 'WE8ISO8859P1') = ?? ?? ?? A B C |
De forma parcial | CONVERT |
La función CONVERT de MySQL requiere algunos ajustes en la sintaxis y los parámetros para mostrar los resultados exactos como Oracle:CONVERT('Ä Ê Í A B C ' USING utf8) = Ä Ê Í A B C |
TO_CHAR (string/numérico) |
La función convierte un número o una fecha en una string:TO_CHAR(22.73,'$99.9') = $22.7 |
No | FORMAT |
La función FORMAT de MySQL realiza un formato de “#,###.##” de un número, lo redondea a una cantidad determinada de decimales y, luego, muestra el resultado como una string; 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 string 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 |
De forma parcial con diferente nombre de función y formato de fecha/hora | STR_TO_DATE |
La función STR_TO_DATE de MySQL toma una string y muestra una fecha especificada por formato de fecha/hora:STR_TO_DATE( '2019/01/01', '%Y/%m/%d') = 2019-01-01 |
TO_NUMBER |
Convierte la expresión en un valor de un tipo de datos NUMBER :TO_NUMBER('01234') = 1234 |
No | CAST |
Como alternativa, usa la función CAST de MySQL para mostrar el mismo resultado que Oracle TO_NUMBER :CAST('01234' as SIGNED) = 1234 |
Funciones SELECT condicionales
Función de Oracle | Implementación o especificación de la función de Oracle | Equivalente de MySQL | Función correspondiente de MySQL | Implementación o especificación de funciones de MySQL |
---|---|---|---|---|
CASE |
La declaración CASE elige entre una secuencia de condiciones y ejecuta una declaració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 del control condicional IF/ELSE dentro de la declaración SELECT :CASE WHEN condition THEN result [WHEN ...] [ELSE result] END |
Funciones nulas
Función de Oracle | Implementación o especificación de la función de Oracle | Equivalente de MySQL | Función correspondiente de MySQL | Implementación o especificación de funciones de MySQL |
---|---|---|---|---|
COALESCE |
Muestra la primera expresión que no es nula en 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 muestra un valor nulo. Si no son iguales, la función muestra expr1:NULLIF('1', '2') = a |
Sí | NULLIF |
Equivalente a Oracle:NULLIF('1', '2') = a |
NVL |
Reemplaza nulo (se muestra como un espacio en blanco) por una string en los resultados de una consulta:NVL(null, 'a') = a |
No | IFNULL |
La función equivalente de MySQL sería la función IFNULL , que reemplaza los valores nulos por una string determinada:IFNULL(null, 'a') = a |
NVL2 |
Determina el valor que muestra una consulta en función de si una expresión especificada es nula o no. |
No | CASE |
La declaración CASE elige entre una secuencia de condiciones y ejecuta una declaración correspondiente: CASE WHEN condition THEN result [WHEN ...] [ELSE result] END |
Funciones de identificador y entorno
Función de Oracle | Implementación o especificación de la función de Oracle | Equivalente de MySQL | Función correspondiente de MySQL | Implementación o especificación de funciones de MySQL |
---|---|---|---|---|
SYS_GUID |
Genera y muestra un identificador único global (valor RAW) compuesto por 16 bytes:SELECT SYS_GUID() FROM DUAL = 8EFA4A31468B4C6DE05011AC0200009E |
No | REPLACE y UUID |
Como una solución alternativa, usa las funciones REPLACE y UUID de MySQL a fin de simular la función SYS_GUID de Oracle:REPLACE( UUID(), '-', '') |
UID |
Muestra un número entero que identifica de forma única al usuario de la sesión (el usuario que accedió): SELECT UID FROM DUAL = 43 |
No | N/A | No disponible |
USER |
Muestra el nombre de usuario de la sesión actual:SELECT USER FROM DUAL = UserName |
De forma parcial | USER + INSTR + SUBSTR |
La función USER de MySQL muestra el nombre de usuario y el servidor de conexión (root@IP ). Para recuperar solo el nombre de usuario, usa funciones complementarias adicionales:SELECT SUBSTR(USER(), 1, INSTR(USER(), '@') -1) FROM DUAL = root |
USERENV |
Muestra información sobre la sesión de usuario actual con la configuración de parámetros actual:SELECT USERENV('LANGUAGE') FROM DUAL = ENGLISH_AMERICA.AL32UTF8 |
No | SHOW SESSION VARIABLES |
Usa la declaració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 un ROWID único para identificar la fila en la tabla. ROWID es la dirección de la fila que contiene el número de objeto de datos, el bloque de datos de la fila, la posición de la fila y el archivo de datos. |
No | No disponible | Si es posible, intenta emular la misma funcionalidad con otras funciones de MySQL. |
ROWNUM |
Muestra un número que representa el orden en que Oracle selecciona una fila de una tabla o tablas unidas. | No | No disponible | Si es posible, intenta emular la misma funcionalidad con otras funciones de MySQL o variables de sesión. |
Funciones de agregación (grupo)
Función de Oracle | Implementación o especificación de la función de Oracle |
Equivalente de MySQL |
Función correspondiente de MySQL | Implementación o especificación de funciones de MySQL |
---|---|---|---|---|
AVG |
Muestra el valor promedio de la columna o expresión. | Sí | AVG |
Equivalente a Oracle |
COUNT |
Muestra la cantidad de filas que muestra una consulta. | Sí | COUNT |
Equivalente a Oracle |
COUNT (DISTINCT) |
Muestra el número de valores únicos en la columna o expresión. | Sí | COUNT (DISTINCT) |
Equivalente a Oracle |
MAX |
Muestra el valor máximo de la columna o expresión. | Sí | MAX |
Equivalente a Oracle |
MIN |
Muestra el valor mínimo de la columna o expresión. | Sí | MIN |
Equivalente a Oracle |
SUM |
Muestra la suma del valor de la columna o expresión. | Sí | SUM |
Equivalente a Oracle |
LISTAGG |
Muestra los datos dentro de cada grupo mediante una sola fila especificada en la cláusula ORDER BY mediante la concatenación de los valores de la columna de medición: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 mostrar resultados similares a los de Oracle. Verás diferencias de sintaxis en ciertos casos:SELECT GROUP_CONCAT( DEPARTMENT_NAME ORDER BY DEPARTMENT_NAME SEPARATOR ', ') DEPT FROM DEPARTMENTS; |
Recuperación de Oracle 12c
Función de Oracle | Implementación o especificación de la función de Oracle |
Equivalente de MySQL |
Función correspondiente de MySQL | Implementación o especificación de funciones de MySQL |
---|---|---|---|---|
FETCH |
Recupera 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 recuperar 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 del operador y las subconsultas son relativamente sencillas y no requieren ningún esfuerzo adicional.
Notas de la conversión
Examina y aborda los formatos de fecha porque los formatos de Oracle y MySQL muestran diferentes resultados predeterminados:
- La función
SYSDATE
de Oracle muestra01-AUG-19
de forma predeterminada. - La función
SYSDATE()
de MySQL muestra2019-08-01 12:04:05
de forma predeterminada. - Los formatos de fecha y hora se pueden configurar mediante las funciones
[DATE_FORMAT](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format)
de MySQL 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 | Implementación o especificación de funciones de 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 declaraciones JOIN y a fin de 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 analíticas y de clasificación)
Las funciones analíticas de Oracle amplían la funcionalidad de las funciones analíticas de SQL estándar, ya que proporcionan capacidades para calcular valores agregados basados en un grupo de filas. Estas funciones se pueden aplicar a conjuntos de resultados con particiones lógicas dentro del alcance de una sola expresión de consulta. Por lo general, se usan en combinación con informes de inteligencia empresarial y estadísticas, con el potencial de aumentar el rendimiento de las consultas como alternativa a fin de lograr el mismo resultado con un código SQL más analítico.
Notas de la conversión
- La versión 5.7 de MySQL no proporciona funciones analíticas para admitir una conversión de instrucciones de SQL sencilla. Sin embargo, esta funcionalidad se agregó de forma parcial en MySQL versión 8, lo que hace que la conversión de funciones analíticas sea un punto a tener en cuenta. Es probable que esto requiera esfuerzo manual en el proceso de migración.
- Una solución opcional es volver a escribir el código para quitar el uso de funciones analíticas, revertir 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árquicas | CONNECT BY HIER_ANCESTOR HIER_CHILD_COUNT HIER_DEPTH HIER_LEVEL HIER_ORDER HIER_PARENT HIER_TOP |
No |
Lag | LAG LAG_VARIANCE LAG_VARIANCE_PERCENT LEAD LEAD_VARIANCE LEAD_VARIANCE_PERCENT |
No |
Expresión de tabla común (CTE)
Las CTE proporcionan una forma de implementar la lógica del código secuencial a fin de reutilizar el código SQL que puede ser demasiado complejo o no eficiente para varios usos. Las CTE se pueden nombrar y, luego, usar en varias partes de una instrucción de SQL mediante la cláusula WITH
.
Notas de la conversión
- La versión 5.7 de MySQL no admite CTE, pero la versión 8 de MySQL sí.
- Como una solución alternativa, usa tablas derivadas o SubQueries, o reescribe la instrucción de SQL para eliminar la funcionalidad de 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; |
Declaración MERGE
La declaración MERGE
(o UPSERT
) proporciona un medio para especificar instrucciones de SQL individuales que realizan operaciones DML de forma condicional en una operación MERGE
, en lugar de una sola operación DML, que se ejecuta por separado. Selecciona registros de la tabla de origen y, luego, especifica una estructura lógica a fin de realizar de forma automática 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 declaración determinista, lo que significa que una vez que la declaración MERGE
procesa una fila, no se puede volver a procesar mediante la misma declaración MERGE
.
Notas de la conversión
A diferencia de Oracle, la versión 5.7 de MySQL no admite la funcionalidad MERGE
. Para simular de forma parcial la funcionalidad de MERGE
, MySQL proporciona las instrucciones REPLACE
y INSERT… ON DUPLICATE KEY UPDATE
:
REPLACE
: Funciona de la misma manera que una declaraciónINSERT
, excepto que si una fila anterior de la tabla tiene el mismo valor que una fila nueva para un índicePRIMARY KEY
oUNIQUE
, la fila anterior se borra antes de insertar la fila nueva.INSERT… ON DUPLICATE KEY UPDATE
: Si una fila insertada causara un valor duplicado en un índicePRIMARY KEY
oUNIQUE
, se produce unUPDATE
de la fila anterior 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 funcionalidad de MERGE
en un procedimiento almacenado para administrar las operaciones de DML, mediante comandos INSERT
, UPDATE
y DELETE
con excepciones y manejo de duplicaciones.
Sugerencias de instrucciones de SQL
Oracle proporciona una gran colección de sugerencias de consulta de SQL que permite a los usuarios influir en el comportamiento del optimizador y en su toma de 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: INDEX HINTS
y OPTIMIZER
HINTS
.
Las sugerencias del optimizador de MySQL proporcionan la capacidad de controlar el comportamiento del optimizador dentro de instrucciones de SQL individuales, por ejemplo:
SELECT /*+ NO_RANGE_OPTIMIZATION(tbl PRIMARY, col1_idx) */ col1 FROM tbl;
Sugerencias del optimizador disponibles para la versión 5.7 de MySQL
Nombre de la sugerencia | Descripción general de la sugerencia | Alcances aplicables |
---|---|---|
BKA, NO_BKA |
Afecta el procesamiento de unión de acceso a las claves por lotes | Bloque de consultas, tabla |
BNL, NO_BNL |
Afecta el procesamiento de unión de bucle anidado de bloque | Bloque de consultas, tabla |
MAX_EXECUTION_TIME |
Limita el tiempo de ejecución de la declaración | Global |
MRR, NO_MRR |
Afecta la optimización de lectura en varios rangos | Tabla, índice |
NO_ICP |
Afecta la optimización de pushdown de la condición del índice | Tabla, índice |
NO_RANGE_OPTIMIZATION |
Afecta la optimización del rango | Tabla, índice |
QB_NAME |
Asigna un nombre al bloque de consulta | Bloque de consulta |
SEMIJOIN, NO_SEMIJOIN |
Afecta las estrategias de semiunión | Bloque de consulta |
SUBQUERY |
Afecta la materialización, estrategias de SubQuery IN a EXISTS . |
Bloque de consulta |
Las sugerencias de índice de MySQL proporcionan al optimizador información sobre cómo elegir índices durante el procesamiento de 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 la conversión
Debido a que existen diferencias fundamentales entre Oracle y el optimizador de MySQL, y dado que existe alguna superposición entre las sugerencias de consulta de Oracle y MySQL, recomendamos que conviertas cualquier instrucción de SQL de Oracle que contenga sugerencias de consulta no especificadas sobre la base de datos de MySQL de destino.
Realiza ajustes de rendimiento de MySQL a través de herramientas de MySQL (por ejemplo, MySQL Workbench para paneles de rendimiento en tiempo real), y características como examinar consultas mediante planes de ejecución y ajustar la instancia o los parámetros de sesión según el caso práctico.
Planes de ejecución
El objetivo principal de los planes de ejecución es proporcionar una mirada interna a las elecciones que realiza 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 declaraciones SELECT
, INSERT
, UPDATE
y DELETE
para los usuarios de la base de datos, lo que también permite que los administradores tengan una mejor visión de las consultas y operaciones de DML específicas. Son útiles en especial cuando necesitas ajustar el rendimiento de las consultas, por ejemplo, para determinar el rendimiento del índice o 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 las conversiones
Los planes de ejecución no son objetos de base de datos que se deban migrar; en su lugar, son una herramienta para analizar las diferencias de rendimiento entre Oracle y MySQL que ejecutan la misma declaración en conjuntos de datos idénticos.
MySQL no admite la misma sintaxis, funcionalidad o 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 de procedimiento extendido de Oracle que se usa para crear, almacenar y aplicar soluciones basadas en código dentro de la base de datos. En general, las funciones y los procedimientos almacenados en la base de datos son elementos de código que constan de ANSI SQL y del lenguaje de procedimiento extendido de SQL, por ejemplo, PL/SQL para Oracle, PL/pgSQL para PostgreSQL, y lenguaje de procedimiento de MySQL para MySQL. MySQL usa el mismo nombre que la base de datos para su propio lenguaje de procedimiento extendido.
El propósito de estos procedimientos almacenados y funciones es proporcionar soluciones para aquellos requisitos que son más adecuados para ejecuciones desde la base de datos y no desde la aplicación (por ejemplo, rendimiento, compatibilidad y seguridad). Aunque los procedimientos almacenados y las funciones usan PL/SQL, los procedimientos almacenados se usan en especial para realizar operaciones DDL/DML, y las funciones se usan en especial a fin de realizar cálculos con el objetivo de mostrar resultados específicos.
Lenguaje de procedimiento de PL/SQL a MySQL
Desde la perspectiva de la migración de código de PL/SQL a MySQL, la implementación de procedimientos de MySQL es diferente de la de Oracle. Por lo tanto, se requiere la migración de código para convertir la funcionalidad de PL/SQL de Oracle en procedimientos almacenados y funciones en MySQL. Además, MySQL no es compatible con Oracle Package y Package Body, por lo que, cuando realices la conversión de código, conviértelos en unidades individuales de código de MySQL (o analízalos). Ten en cuenta que los procedimientos almacenados y las funciones de MySQL también se denominan rutinas.
Propietario de objetos de código
En Oracle, el propietario de un procedimiento almacenado o una función 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).
Seguridad y privilegios de objetos de código
En Oracle, para crear un procedimiento almacenado o una función, el usuario debe tener el privilegio del sistema CREATE PROCEDURE
(a fin de crear procedimientos o funciones con 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 ejecutar. La cláusula DEFINER
de MySQL define el creador del usuario para el objeto de código, y el usuario debe tener los privilegios adecuados, como CREATE ROUTINE
.
Sintaxis de funciones y procedimiento almacenados de MySQL
En el siguiente ejemplo, se muestra la sintaxis de la función y el procedimiento almacenado 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