Este documento faz parte de uma série que fornece informações importantes e orientações relacionadas a planejamento e execução de migrações de banco de dados Oracle® 11g/12c para o Cloud SQL para MySQL versão 5.7, instâncias de segunda geração. A série inclui as partes a seguir:
- Como migrar usuários do Oracle para o Cloud SQL para MySQL: terminologia e funcionalidade
- Como migrar usuários do Oracle para o Cloud SQL para MySQL: tipos de dados, usuários e tabelas
- Como migrar usuários do Oracle para o Cloud SQL para MySQL: consultas, procedimentos armazenados, funções e gatilhos (este documento)
- Como migrar usuários da Oracle para o Cloud SQL para MySQL: segurança, operações, monitoramento e geração de registros
Consultas
O Oracle e o Cloud SQL para MySQL são compatíveis com o padrão ANSI SQL. Geralmente, é simples migrar instruções SQL usando apenas elementos de sintaxe básicos (por exemplo, não especificando funções escalares ou qualquer outro recurso estendido do Oracle). Na seção a seguir, discutimos elementos comuns de consulta do Oracle e os equivalentes correspondentes do Cloud SQL para MySQL.
Sintaxe básica de SELECT e FROM
Nome do recurso do Oracle ou nome da sintaxe | Visão geral ou implementação do Oracle | Compatível com MySQL | Solução alternativa ou correspondente do MySQL |
---|---|---|---|
Sintaxe básica do SQL para recuperação de dados | SELECT FROM WHERE GROUP BY HAVING ORDER BY |
Sim | SELECT FROM WHERE GROUP BY HAVING ORDER BY |
SELECT para impressão de saída |
SELECT 1 FROM DUAL |
Sim | SELECT 1 OR SELECT 1 FROM DUAL |
Aliases de coluna | SELECT COL1 AS C1 |
Sim | SELECT COL1 AS C1 OR SELECT COL1 C1 |
Diferenciação entre maiúsculas e minúsculas no nome da tabela |
Nenhuma diferenciação de maiúsculas e minúsculas (por exemplo, o nome da tabela pode ser orders e/ou ORDERS ). |
Não | Diferencia maiúsculas de minúsculas de acordo com o nome da tabela definido (por exemplo, o nome da tabela pode ser apenas orders ou ORDERS ). |
Leia mais detalhes sobre a sintaxe SELECT
do MySQL.
- Visualizações in-line
- As visualizações in-line (também conhecidas como tabelas derivadas) são instruções
SELECT
, localizadas na cláusulaFROM
e usadas como uma subconsulta. - As visualizações in-line podem ajudar a simplificar consultas complexas, removendo cálculos compostos ou eliminando operações de junção, ao mesmo tempo em que compilam várias consultas separadas em uma única consulta simplificada.
- Observação de conversão: as visualizações in-line do Oracle não exigem o uso de aliases, enquanto o MySQL exige aliases específicos para cada visualização in-line.
- As visualizações in-line (também conhecidas como tabelas derivadas) são instruções
A tabela a seguir apresenta um exemplo de conversão do Oracle para MySQL, como uma visualização in-line.
Oracle 11g/12c |
---|
SQL> SELECT FIRST_NAME, DEPARTMENT_ID, SALARY, DATE_COL FROM EMPLOYEES, (SELECT SYSDATE AS DATE_COL FROM DUAL); O resultado será assim: 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 |
Sem alias para a visualização in-line:mysql> SELECT FIRST_NAME, DEPARTMENT_ID, SALARY, DATE_COL FROM EMPLOYEES, (SELECT SYSDATE() AS DATE_COL FROM DUAL); Como adicionar um alias à visualização in-line: mysql> SELECT FIRST_NAME, DEPARTMENT_ID, SALARY, DATE_COL FROM EMPLOYEES, (SELECT SYSDATE() AS DATE_COL FROM DUAL) AS A1; O resultado será assim: +-------------+---------------+----------+---------------------+ | 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 | |
Instruções JOIN
As instruções JOIN
do Oracle são compatíveis com as instruções
JOIN
do MySQL, exceto a cláusula FULL JOIN
. Além disso, as instruções JOIN
do MySQL aceitam o uso de sintaxe alternativa, como a cláusula USING
, a cláusula WHERE
em vez da cláusula ON
e o uso de SUBQUERY
na instrução JOIN
.
Na tabela a seguir, veja um exemplo de conversão JOIN.
Tipo JOIN do Oracle | Compatível com MySQL | Sintaxe de JOIN do MySQL |
---|---|---|
INNER JOIN |
Sim | SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E JOIN DEPARTMENTS D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID; |
CROSS JOIN |
Sim | SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E CROSS JOIN DEPARTMENTS D |
FULL JOIN |
Não | Para uma solução alternativa, use UNION com instruções LEFT e RIGHT JOIN . |
LEFT JOIN [ OUTER ] |
Sim | SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E LEFT JOIN DEPARTMENTS D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID; |
RIGHT JOIN [ OUTER ] |
Sim | SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E RIGHT JOIN DEPARTMENTS D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID; |
SUBQUERY |
Sim | 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 e MINUS
O MySQL não é compatível com as funções INTERSECT
e MINUS
do Oracle, exceto as funções UNION
e UNION ALL
:
UNION
: anexa os conjuntos de resultados de duas ou mais instruçõesSELECT
e elimina registros duplicados.UNION ALL
: anexa os conjuntos de resultados de duas ou mais instruçõesSELECT
sem eliminar registros duplicados.INTERSECT
: retorna a interseção de duas ou mais instruçõesSELECT
somente se houver um registro nos dois conjuntos de dados.MINUS
: compara duas ou mais instruçõesSELECT
, retornando apenas linhas distintas da primeira consulta que não são retornadas pelas outras instruções.
Observações sobre a conversão
Ao converter as funções INTERSECT
e MINUS
do Oracle em MySQL, use as instruções JOIN
e IN
e EXISTS
como uma solução alternativa.
Exemplos
Função Oracle | Implementação do Oracle | Compatível com MySQL | Solução alternativa ou correspondente do MySQL |
---|---|---|---|
UNION |
SELECT COL1 FROM TBL1 UNION SELECT COL1 FROM TBL2 |
Sim | SELECT COL1 FROM TBL1 UNION SELECT COL1 FROM TBL2 |
UNION ALL |
SELECT COL1 FROM TBL1 UNION ALL SELECT COL1 FROM TBL2 |
Sim | SELECT COL1 FROM TBL1 UNION ALL SELECT COL1 FROM TBL2 |
INTERSECT |
SELECT COL1 FROM TBL1 INTERSECT SELECT COL1 FROM TBL2 |
Não | SELECT COL1 FROM TBL1 WHERE COL1 IN (SELECT COL1 FROM TBL2) |
MINUS |
SELECT COL1 FROM TBL1 MINUS SELECT COL1 FROM TBL2 |
Não | SELECT A.COL1 FROM TBL1 A LEFT JOIN TBL2 B ON USING(COL1) WHERE B.COL1 IS NULL |
Funções escalares (de linha única) e de grupo
O MySQL fornece uma extensa lista de funções escalares (de linha única) e de agregação. Algumas das funções do MySQL são semelhantes às versões equivalentes do Oracle (por nome e funcionalidade ou com um nome diferente, mas com funcionalidade semelhante). Ainda que as funções do MySQL possam ter nomes idênticos aos equivalentes do Oracle, elas podem exibir funcionalidades diferentes.
As tabelas a seguir descrevem onde o Oracle e o MySQL são equivalentes por nome e funcionalidade (especificados por "Sim") e onde uma conversão é recomendada (todos os casos, exceto "Sim").
Funções de caracteres
Função Oracle | Especificação ou implementação da função do Oracle | Equivalente do MySQL | Função correspondente do MySQL | Especificação ou implementação da função do MySQL |
---|---|---|---|---|
CONCAT(str1,str2) |
Retorna str1 concatenado com str2:CONCAT('A', 1) = A1 |
Sim | CONCAT |
Equivalente do Oracle:CONCAT('A', 1) = A1 |
LOWER/UPPER |
Retorna char, com todas as letras minúsculas ou maiúsculas:LOWER('SQL') = sql |
Sim | LOWER/UPPER |
Equivalente do Oracle:LOWER('SQL') = sql |
LPAD/RPAD(expr1,n,expr2) |
Retorna expr1, à esquerda ou à direita preenchidos com caracteres n com a sequência de caracteres em expr2:LPAD('A',3,'*') = **A |
Sim | LPAD/RPAD |
Equivalente do Oracle:LPAD('A',3,'*') = **A |
SUBSTR(char,p,n) |
Retorne uma parte de char, começando na posição do caractere p, com comprimento de substring de n caracteres:SUBSTR('MySQL', 3, 3) = SQL |
Sim | SUBSTR(char,p,n) |
Equivalente do Oracle:SUBSTR('MySQL', 3, 3) = SQL |
INSTR(index,str) |
Retorna a posição (index) da string str:INSTR('MySQL', 'y') = 2 |
Sim | INSTR |
Equivalente do Oracle:INSTR('MySQL', 'y') = 2 |
REPLACE(char,str1,str2) |
Retorna char com cada ocorrência de uma string de pesquisa substituída por uma string de substituição: REPLACE('ORADB', 'ORA', 'MySQL') |
Sim | REPLACE(char,str1,str2) |
Equivalente do Oracle:REPLACE('ORADB', 'ORA', 'MySQL') |
TRIM(str) |
Corte caracteres iniciais ou finais (ou ambos) de uma string:TRIM(both '-' FROM '-MySQL-') = MySQL |
Sim | TRIM(str) |
Equivalente do Oracle:TRIM(both '-' FROM '-MySQL-') = MySQL |
LTRIM/RTRIM(str) |
Remove da extremidade esquerda ou direita da string todos os caracteres que aparecem na pesquisa:LTRIM(' MySQL', ' ') = MySQL |
Parcialmente | LTRIM/RTRIM(str) |
Função R/LTRIM do Oracle, exceto uma substituição para o parâmetro (espaço em branco ou string). O MySQL R/LTRIM só elimina espaços em branco, aceitando apenas a string de entrada:LTRIM(' MySQL') = MySQL |
ASCII(char) |
Retorna a representação decimal no conjunto de caracteres do banco de dados do primeiro caractere de char: ASCII('A') = 65 |
Sim | ASCII(char) |
Equivalente do Oracle:ASCII('A') = 65 |
CHR(char) |
Retorna o valor do código ASCII, que é um valor numérico entre 0 e 225, para um caractere:CHR(65) = A |
Parcialmente com nome de função diferente | CHAR(char) |
O MySQL usa a função CHAR para a mesma funcionalidade. Portanto, você precisa modificar um nome de função:CHAR(65) = A |
LENGTH(str) |
Retorna o comprimento de uma determinada string:LENGTH ('MySQL') = 5 |
Sim | LENGTH(str) |
Equivalente do Oracle:LENGTH('MySQL') = 5 |
REGEXP_REPLACE(str1,expr,str2) |
Procure um padrão de expressão regular em uma string:REGEXP_REPLACE('John', '[hn].', '1') = Jo1 |
Não | N/A | Compatível apenas com a versão 8 do MySQL. Como solução alternativa, use a função REPLACE , se possível, ou converta para a camada do aplicativo |
REGEXP_SUBSTR(str,expr) |
Estende a funcionalidade da função SUBSTR pesquisando um padrão de expressão regular em uma string:REGEXP_SUBSTR('https://console.cloud.google.com/sql/instances','https://([[:alnum:]]+\.?){3,4}/?') = https://console.cloud.google.com/ |
Não | N/A | Compatível apenas com a versão 8 do MySQL. Para uma solução alternativa, use a função SUBSTR , se possível, ou converta a funcionalidade para a camada do aplicativo. |
REGEXP_COUNT(str,expr) |
Retorna o número de vezes que um padrão ocorre em uma string de origem. | Não | N/A | Para uma solução alternativa, converta a funcionalidade para a camada do aplicativo. |
REGEXP_INSTR(index,expr) |
Pesquise uma posição de string (índice) para um padrão de expressão regular. | Não | N/A | Compatível apenas com a versão 8 do MySQL. |
REVERSE(str) |
Retornar uma string invertidaREVERSE('MySQL') = LQSyM |
Sim | REVERSE |
Equivalente do Oracle:REVERSE('MySQL') = LQSyM |
Funções numéricas
Função Oracle | Especificação ou implementação da função do Oracle | Equivalente do MySQL | Função correspondente do MySQL | Especificação ou implementação da função do MySQL |
---|---|---|---|---|
ABS(n) |
Valor absoluto de n: ABS(-4.6) = 4.6 |
Sim | ABS |
Equivalente do Oracle:ABS(-4.6) = 4.6 |
CEIL(n) |
Retorna o menor número inteiro maior ou igual a n:CEIL(21.4) = 22 |
Sim | CEIL |
Equivalente do Oracle:CEIL(21.4) = 22 |
FLOOR(n) |
Retorna o maior inteiro igual ou menor que n: FLOOR(-23.7) = -24 |
Sim | FLOOR |
Equivalente do Oracle:FLOOR(-23.7) = -24 |
MOD(m,n) |
Retorna o restante de m dividido por n:MOD(10, 3) = 1 |
Sim | MOD(m,n) |
Equivalente do Oracle:MOD(10,3) = 1 |
ROUND(m,n) |
Retorna m arredondado para n casas inteiras à direita do ponto decimal:ROUND(1.39,1) = 1.4 |
Sim | ROUND |
Equivalente do Oracle:ROUND(1.39,1) = 1.4 |
TRUNC(n1, n2) |
Retorna n1 truncado para n2 casas decimais:TRUNC(99.999) = 99 TRUNC(99.999,0) = 99 |
Parcialmente com nome de função diferente | TRUNCATE(n1, n2) |
A função TRUNCATE do MySQL precisa aceitar um número de entrada e um número inteiro para especificar o valor de precisão à direita do ponto decimal:TRUNCATE(99.999,0) = 99 |
Funções de data e hora
Função Oracle | Especificação ou implementação da função do Oracle | Equivalente do MySQL | Função correspondente do MySQL | Especificação ou implementação da função do MySQL |
---|---|---|---|---|
SYSDATE |
Retorna a data e a hora atuais definidas para o sistema operacional em que o servidor de banco de dados reside:SELECT SYSDATE FROM DUAL = 31-JUL-2019 |
Parcialmente | SYSDATE() |
O SYSDATE() do MySQL precisa incluir parênteses e retornar um formato de data/hora diferente da função SYSDATE do Oracle:SELECT SYSDATE() FROM DUAL; = 2019-01-31 10:01:01.0 A formatação de data/hora pode ser alterada no nível da sessão |
SYSTIMESTAMP |
Retorna a data do sistema, incluindo segundos fracionários e fuso horário:SELECT SYSTIMESTAMP FROM DUAL = 01-JAN-19 07.37.11.622187000 AM +00:00 |
Parcialmente com nome de função diferente | CURRENT_TIMESTAMP |
O MySQL retorna uma formatação de data/hora diferente do Oracle. Uma formatação de data é necessária (ou uma função de data diferente) para corresponder à formatação de data/hora original:SELECT CURRENT_TIMESTAMP FROM DUAL = 2019-01-31 06:55:07 |
LOCAL_TIMESTAMP |
Retorna a data e a hora atuais no fuso horário da sessão em um valor do tipo de dados TIMESTAMP :SELECT LOCAL_TIMESTAMP FROM DUAL = 01-JAN-19 10.01.10.123456 PM |
Parcialmente com formatação de data/hora diferente. | LOCAL_TIMESTAMP |
O MySQL retorna uma formatação de data/hora diferente do Oracle. A formatação de data/hora é obrigatória (ou uma função de data diferente) para corresponder à formatação de data/hora original:SELECT LOCAL_TIMESTAMP FROM DUAL = 2019-01-01 10:01:01.0 |
CURRENT_DATE |
Retorna a data atual no fuso horário da sessão:SELECT CURRENT_DATE FROM DUAL = 31-JAN-19 |
Parcialmente com formatação de data/hora diferente | CURRENT_DATE |
O MySQL retorna uma formatação de data/hora diferente do Oracle. A formatação de data/hora é obrigatória (ou uma função de data diferente) para corresponder à formatação de data/hora original:SELECT CURRENT_DATE FROM DUAL = 2019-01-31 |
CURRENT_TIMESTAMP |
Retorna a data e a hora atuais no fuso horário da sessão:SELECT CURRENT_TIMESTAMP FROM DUAL = 31-JAN-19 06.54.35.543146 AM +00:00 |
Parcialmente com formatação de data/hora diferente | CURRENT_TIMESTAMP |
O MySQL retorna uma formatação de data/hora diferente do Oracle. A formatação de data/hora é obrigatória (ou uma função de data diferente) para corresponder à formatação de data/hora original:SELECT CURRENT_TIMESTAMP FROM DUAL = 2019-01-31 06:55:07 |
ADD_MONTHS |
Retorna a data mais os meses inteiros:ADD_MONTHS(SYSDATE, 1) = 31-JAN-19 |
Parcialmente com nome de função diferente | ADDDATE |
Para conseguir a mesma funcionalidade, o MySQL usa a função ADDDATE :ADDDATE(SYSDATE(), 1) = 2019-08-01 06:42:49.0 Por padrão, o MySQL retorna data/hora e intervalo/formato diferentes do Oracle. A formatação de data/hora é obrigatória (ou uma função de data diferente) para corresponder à formatação de data/hora original. |
EXTRACT (parte da data) |
Retorna o valor de um campo de data/hora especificado de uma expressão de data/hora ou intervalo:EXTRACT(YEAR FROM DATE '2019-01-31') = 2019 |
Sim | EXTRACT (parte da data) |
Equivalente do Oracle:EXTRACT(YEAR FROM DATE '2019-01-31') = 2019 |
LAST_DAY |
Retorna a data do último dia do mês:LAST_DAY('01-JAN-2019') = 31-JAN-19 |
Parcialmente com formatação de data/hora diferente | LAST_DAY |
O MySQL retorna uma formatação de data/hora diferente do Oracle. A formatação de data/hora é obrigatória (ou uma função de data diferente) para corresponder à formatação de data/hora original:LAST_DAY('2019-01-01') = 2019-01-31 |
MONTH_BETWEEN |
Retorna o número de meses entre as datas date1 e date2:MONTHS_BETWEEN( SYSDATE, SYSDATE-60) = 1.96 |
Parcialmente com nome de função diferente | PERIOD_DIFF(date1,date2) |
A função PERIOD_DIFF do MySQL retorna a diferença em meses como um número inteiro entre dois pontos (formatados como YYMM ou YYYYMM ):PERIOD_DIFF( '201903', '201901') = 2 Para atingir os mesmos valores que a função MONTH_BETWEEN do Oracle, será necessária
uma conversão mais específica |
TO_CHAR (data/hora) |
Converte um tipo de dados de data/hora ou carimbo de data/hora em um valor de tipo de dados VARCHAR2 no formato especificado pelo formato de data:TO_CHAR( SYSDATE,'DD-MM-YYYY HH24:MI:SS') = 01-01-2019 10:01:01 |
Parcialmente com nome de função diferente | DATE_FORMAT |
A função DATE_FORMAT do MySQL formata uma data conforme especificado por uma definição de formato de data:DATE_FORMAT( SYSDATE(),'%d-%m-%Y %H:%i:%s') = 01-01-2019 10:01:01 |
Funções de codificação e decodificação
Função Oracle | Especificação ou implementação da função do Oracle | Equivalente do MySQL | Função correspondente do MySQL | Especificação ou implementação da função do MySQL |
---|---|---|---|---|
DECODE |
Compara uma expressão com cada valor de pesquisa usando a funcionalidade
de uma instrução IF-THEN-ELSE |
Não | CASE |
Use a instrução CASE do MySQL para conseguir uma funcionalidade semelhante. |
DUMP |
Retorna um valor VARCHAR2 que contém o código do tipo de dados, o comprimento em bytes e a representação interna de uma determinada expressão. |
Não | N/A | Incompatível. |
ORA_HASH |
Calcula um valor de hash para uma determinada expressão. | Não | MD5/SHA |
Use o MySQL MD5 para soma de verificação de 128 bits ou a função SHA para soma de verificação de 160 bits para gerar valores de hash |
Funções de conversão
Função Oracle | Especificação ou implementação da função do Oracle | Equivalente do MySQL | Função correspondente do MySQL | Especificação ou implementação da função do MySQL |
---|---|---|---|---|
CAST |
Converte um tipo de dados integrado ou um valor tipado por coleção em outro tipo de dados integrado ou valor tipado por coleção: CAST('1' as int) + 1 = 2 |
Parcialmente | CAST |
A função CAST do MySQL é semelhante à funcionalidade do Oracle, mas em alguns casos ela precisa ser ajustada, dependendo da necessidade de uma conversão explícita ou implícita:CAST('1' AS SIGNED) + 1 = 2 |
CONVERT |
Converte uma string de caracteres de um conjunto de caracteres em outro: CONVERT('Ä Ê Í Õ Ø A B C D E ', 'US7ASCII', 'WE8ISO8859P1') = ?? ?? ?? A B C |
Parcialmente | CONVERT |
A função CONVERT do MySQL requer alguns ajustes na sintaxe e nos parâmetros para retornar os resultados exatos como Oracle:CONVERT('Ä Ê Í A B C ' USING utf8) = Ä Ê Í A B C |
TO_CHAR (string/numérico) |
A função converte um número ou uma data em uma string: TO_CHAR(22.73,'$99.9') = $22.7 |
Não | FORMAT |
A função FORMAT do MySQL executa o formato "#, ###.##" de um número, arredondando-o para um determinado número de casas decimais e, em seguida, retorna o resultado como uma string, que tem funcionalidade diferente do Oracle:CONCAT('$', FORMAT(22.73, 1)) = $22.7 |
TO_DATE |
A função TO_DATE do Oracle converte uma string em uma data pelo formato de data/hora específico da origem:TO_DATE( '2019/01/01', 'yyyy-mm-dd') = 01-JAN-2019 |
Parcialmente com nome de função e formatação de data/hora diferente | STR_TO_DATE |
A função STR_TO_DATE do MySQL usa uma string e retorna uma data especificada pela formatação de data/hora:STR_TO_DATE( '2019/01/01', '%Y/%m/%d') = 2019-01-01 |
TO_NUMBER |
Converte a expressão em um valor de um tipo de dados NUMBER :TO_NUMBER('01234') = 1234 |
Não | CAST |
Como alternativa, use a função CAST do MySQL para retornar o mesmo resultado que TO_NUMBER do Oracle:CAST('01234' as SIGNED) = 1234 |
Funções SELECT condicionais
Função Oracle | Especificação ou implementação da função do Oracle | Equivalente do MySQL | Função correspondente do MySQL | Especificação ou implementação da função do MySQL |
---|---|---|---|---|
CASE |
A instrução CASE escolhe uma sequência de condições e executa uma instrução correspondente com a seguinte sintaxe:CASE WHEN condition THEN result [WHEN ...] [ELSE result] END |
Sim | CASE |
Além da função CASE , o MySQL também é compatível com o uso condicional IF/ELSE na instrução SELECT :CASE WHEN condition THEN result [WHEN ...] [ELSE result] END |
Funções nulas
Função Oracle | Especificação ou implementação da função do Oracle | Equivalente do MySQL | Função correspondente do MySQL | Especificação ou implementação da função do MySQL |
---|---|---|---|---|
COALESCE |
Retorna a primeira expressão não nula na lista de expressões: COALESCE( null, '1', 'a') = a |
Sim | COALESCE |
Equivalente do Oracle:COALESCE( null, '1', 'a') = 1 |
NULLIF |
Compare expr1 e expr2m. Se forem iguais, a função retornará nulo. Se eles não forem iguais, a função retornará expr1: NULLIF('1', '2') = a |
Sim | NULLIF |
Equivalente do Oracle:NULLIF('1', '2') = a |
NVL |
Substitua nulo (retornado em branco) por uma string nos resultados de uma consulta:
NVL(null, 'a') = a |
Não | IFNULL |
A função equivalente do MySQL seria a função IFNULL , que substitui valores nulos por uma determinada string:IFNULL(null, 'a') = a |
NVL2 |
Determine o valor retornado por uma consulta com base no fato de uma expressão especificada ser nula ou não. |
Não | CASE |
A instrução CASE escolhe uma sequência de condições e executa uma instrução correspondente:CASE WHEN condition THEN result [WHEN ...] [ELSE result] END |
Ambiente e funções de identificador
Função Oracle | Especificação ou implementação da função do Oracle | Equivalente do MySQL | Função correspondente do MySQL | Especificação ou implementação da função do MySQL |
---|---|---|---|---|
SYS_GUID |
Gera e retorna um identificador globalmente exclusivo (valor RAW) composto por 16 bytes:SELECT SYS_GUID() FROM DUAL = 8EFA4A31468B4C6DE05011AC0200009E |
Não | REPLACE e UUID |
Para uma solução alternativa, use as funções REPLACE e UUID do MySQL para simular a função SYS_GUID do Oracle:REPLACE( UUID(), '-', '') |
UID |
Retorna um número inteiro que identifica exclusivamente o usuário da sessão (o usuário que fez login): SELECT UID FROM DUAL = 43 |
Não | N/A | N/A |
USER |
Retorna o nome do usuário atual da sessão:SELECT USER FROM DUAL = UserName |
Parcialmente | USER + INSTR + SUBSTR |
A função USER do MySQL retorna o nome de usuário junto com o servidor de conexão (root@IP ). Para recuperar apenas o nome de usuário, use outras funções de suporte:SELECT SUBSTR(USER(), 1, INSTR(USER(), '@') -1) FROM DUAL = root |
USERENV |
Retorna informações sobre a sessão de usuário atual com a configuração de parâmetro atual:SELECT USERENV('LANGUAGE') FROM DUAL = ENGLISH_AMERICA.AL32UTF8 |
Não | SHOW SESSION VARIABLES |
Use a instrução SHOW SESSION VARIABLES do MySQL para ver as configurações da sessão atual:SHOW SESSION VARIABLES LIKE '%collation%'; = utf8_general_ci |
ROWID |
O servidor Oracle atribui a cada linha em cada tabela um ROWID exclusivo para identificar a linha na tabela. O ROWID é o endereço da linha que contém o número do objeto de dados, o bloco de dados da linha, a posição da linha e o arquivo de dados. |
Não | N/A | Se possível, tente emular a mesma funcionalidade com outras funções do MySQL. |
ROWNUM |
Retorna um número que representa a ordem em que uma linha é selecionada pelo Oracle em uma tabela ou em tabelas mescladas. | Não | N/A | Se possível, tente emular a mesma funcionalidade com outras funções do MySQL ou variáveis de sessão. |
Funções de agregação (grupo)
Função Oracle | Especificação ou implementação da função do Oracle |
Equivalente do MySQL |
Função correspondente do MySQL | Especificação ou implementação da função do MySQL |
---|---|---|---|---|
AVG |
Retorna o valor médio da coluna ou expressão. | Sim | AVG |
Equivalente do Oracle |
COUNT |
Retorna o número de linhas retornadas por uma consulta. | Sim | COUNT |
Equivalente do Oracle |
COUNT (DISTINCT) |
Retorna o número de valores exclusivos na coluna ou expressão. | Sim | COUNT (DISTINCT) |
Equivalente do Oracle |
MAX |
Retorna o valor máximo de uma coluna ou expressão. | Sim | MAX |
Equivalente do Oracle |
MIN |
Retorna o valor mínimo da coluna ou expressão. | Sim | MIN |
Equivalente do Oracle |
SUM |
Retorna a soma do valor da coluna ou expressão. | Sim | SUM |
Equivalente do Oracle |
LISTAGG |
Exibe os dados em cada grupo por uma única linha especificada na cláusula ORDER BY , concatenando os valores da coluna de medida:SELECT LISTAGG( DEPARTMENT_NAME, ', ') WITHIN GROUP (ORDER BY DEPARTMENT_NAME) DEPT FROM DEPARTMENTS; |
Não | GROUP_CONCAT |
Use a função MySQL GROUP_CONCAT para retornar resultados semelhantes aos do Oracle. São esperadas diferenças de sintaxe com determinados casos:SELECT GROUP_CONCAT( DEPARTMENT_NAME ORDER BY DEPARTMENT_NAME SEPARATOR ', ') DEPT FROM DEPARTMENTS; |
Busca do Oracle 12c
Função Oracle | Especificação ou implementação da função do Oracle |
Equivalente do MySQL |
Função correspondente do MySQL | Especificação ou implementação da função do MySQL |
---|---|---|---|---|
FETCH |
Recupera linhas de dados do conjunto de resultados de uma consulta de várias linhas: SELECT * FROM EMPLOYEES FETCH FIRST 10 ROWS ONLY; |
Não | LIMIT | Use a cláusula LIMIT do MySQL para recuperar apenas um conjunto específico de registros:SELECT * FROM EMPLOYEES LIMIT 10; |
Filtragem básica, operadores e subconsultas
Durante a conversão, a filtragem básica, as funções do operador e as subconsultas são relativamente simples, exigindo pouco ou nenhum esforço.
Observações sobre a conversão
Examine e resolva os formatos de data porque os formatos Oracle e MySQL retornam resultados padrão diferentes:
- A função
SYSDATE
do Oracle por padrão retorna01-AUG-19
. - Por padrão, a função
SYSDATE()
do MySQL retorna2019-08-01 12:04:05
. - Os formatos de data e hora podem ser definidos usando as funções
[DATE_FORMAT](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format)
ou[STR_TO_DATE](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_str-to-date)
do MySQL.
Função ou subconsulta do Oracle | Equivalente do MySQL | Função ou subconsulta correspondente do MySQL | Especificação ou implementação da função do MySQL |
---|---|---|---|
EXISTS/NOT EXISTS |
Sim | EXISTS/NOT EXISTS |
SELECT * FROM DEPARTMENTS D WHERE EXISTS (SELECT 1 FROM EMPLOYEES E WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID); |
IN/NOT IN |
Sim | IN/NOT IN |
SELECT * FROM DEPARTMENTS D WHERE DEPARTMENT_ID IN (SELECT DEPARTMENT_ID FROM EMPLOYEES E); |
LIKE/NOT LIKE |
Sim | LIKE/NOT LIKE |
SELECT * FROM EMPLOYEES WHERE FIRST_NAME LIKE '_e_n%'; |
BETWEEN/NOT BETWEEN |
Sim | BETWEEN/NOT BETWEEN |
SELECT * FROM EMPLOYEES WHERE EXTRACT(YEAR FROM HIRE_DATE) NOT BETWEEN 2001 and 2004; |
AND/OR |
Sim | AND/OR |
SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID IN(100, 101) AND (SALARY >= 1000 OR HIRE_DATE <= '2006-02-05'); |
SubQuery |
Sim | SubQuery |
O MySQL é compatível com subconsultas no nível SELECT , para instruções JOIN e para filtragem nas 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 | Sim | Operadores | O MySQL é compatível com todos os operadores básicos:> | >= | < | <= | = | <> | != |
Funções analíticas (ou funções de janela e classificação)
As funções analíticas do Oracle estendem a funcionalidade das funções analíticas SQL padrão fornecendo recursos para calcular valores agregados com base em um grupo de linhas. Essas funções podem ser aplicadas a conjuntos de resultados particionados logicamente no escopo de uma única expressão de consulta. Geralmente, eles são usados em combinação com relatórios e análises de negócios, com o potencial de melhorar o desempenho da consulta como uma alternativa para alcançar o mesmo resultado usando um código SQL não analítico mais complexo.
Notas de conversão
- O MySQL versão 5.7 não fornece funções analíticas para oferecer compatibilidade com uma conversão de instruções SQL simples. No entanto, essa funcionalidade foi adicionada parcialmente no MySQL versão 8 (em inglês), tornando a conversão de funções analíticas um ponto a ser considerado, provavelmente exigindo esforço manual no processo de migração.
- Uma solução opcional é reescrever o código para remover o uso de funções analíticas, reverter para soluções de código SQL mais tradicionais ou mover essa lógica para uma camada de aplicativo.
Na tabela a seguir, veja as funções analíticas comuns do Oracle.
Família de funções | Funções relacionadas | Compatível com o MySQL 5.7 |
---|---|---|
Análise e classificação | RANK AVERAGE_RANK DENSE_RANK RANK ROW_NUMBER PERCENT_RANK CUME_DIST NTILE FIRST_VALUE LAST_VALUE OVER (PARTITION BY...) |
Não |
Hierárquica | CONNECT BY HIER_ANCESTOR HIER_CHILD_COUNT HIER_DEPTH HIER_LEVEL HIER_ORDER HIER_PARENT HIER_TOP |
Não |
Atraso | LAG LAG_VARIANCE LAG_VARIANCE_PERCENT LEAD LEAD_VARIANCE LEAD_VARIANCE_PERCENT |
Não |
Expressão de tabela comum (CTE)
Os CTEs fornecem uma maneira de implementar a lógica do código sequencial para reutilizar o código SQL que pode ser muito complexo ou não eficiente para uso múltiplo. Os CTEs podem ser nomeados e usados várias vezes em diferentes partes de uma instrução SQL usando a cláusula WITH
.
Observações sobre a conversão
- O MySQL versão 5.7 não é compatível com CTEs, mas o MySQL versão 8 sim.
- Para uma solução alternativa, use tabelas derivadas ou subconsultas ou reescreva a instrução SQL para eliminar a funcionalidade de CTE.
Exemplos
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; |
Instrução MERGE
A instrução MERGE
(ou UPSERT
) fornece um meio para especificar instruções SQL que executam condicionalmente operações DML em uma operação MERGE
, em vez de uma única operação DML, executada separadamente. Ele seleciona registros da tabela de origem e, em seguida, especificando uma estrutura lógica, executa automaticamente várias operações DML na tabela de destino. Esse recurso ajuda a evitar o uso de várias inserções, atualizações ou exclusões. Observe que MERGE
é uma instrução determinística, ou seja, depois que uma linha é processada pela instrução MERGE
, ela não pode ser processada novamente usando a mesma instrução MERGE
.
Notas de conversão
Ao contrário do Oracle, o MySQL versão 5.7 não é compatível com a funcionalidade MERGE
. Para
simular parcialmente a funcionalidade MERGE
, o MySQL
fornece as instruções
REPLACE
e
INSERT… ON DUPLICATE KEY UPDATE
:
REPLACE
: funciona da mesma maneira que uma instruçãoINSERT
, exceto se uma linha antiga na tabela tiver o mesmo valor de uma nova linha para um índicePRIMARY KEY
ouUNIQUE
. Nesse caso, a linha antiga é excluída antes que a nova linha seja inserida.INSERT… ON DUPLICATE KEY UPDATE
: se uma linha inserida causar um valor duplicado em um índicePRIMARY KEY
ouUNIQUE
, ocorrerá umUPDATE
da linha antiga para eliminar a exceção de chave duplicada, por exemplo: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;
Outra solução seria converter a funcionalidade MERGE
em um procedimento armazenado para gerenciar operações DML, usando os comandos INSERT
, UPDATE
e DELETE
com processamento de exceções e duplicações.
Dicas de instrução SQL
O Oracle fornece uma grande coleção de dicas de consulta SQL que permite que os usuários influenciem o comportamento do otimizador e a tomada de decisão, com o objetivo de produzir planos de execução de consulta mais eficientes. O Oracle é compatível com mais de 60 dicas de banco de dados diferentes. O MySQL fornece um conjunto limitado de dicas de consulta.
Em geral, o MySQL versão 5.7 é compatível com dois tipos de dicas de consulta: OPTIMIZER
HINTS
e INDEX HINTS
.
As Dicas do otimizador do MySQL permitem controlar o comportamento do otimizador em instruções
SQL individuais, por exemplo:
SELECT /*+ NO_RANGE_OPTIMIZATION(tbl PRIMARY, col1_idx) */ col1 FROM tbl;
Dicas do otimizador MySQL 5.7 disponíveis
Nome da dica | Visão geral da dica | Escopos aplicáveis |
---|---|---|
BKA, NO_BKA |
Afeta o processamento da junção de acesso à chave em lote | Bloco de consulta, tabela |
BNL, NO_BNL |
Afeta o processamento da junção de loop aninhado | Bloco de consulta, tabela |
MAX_EXECUTION_TIME |
Limita o tempo de execução da instrução | Global |
MRR, NO_MRR |
Afeta a otimização de leitura em vários intervalos | Tabela, índice |
NO_ICP |
Afeta a otimização de pushdown da condição do índice | Tabela, índice |
NO_RANGE_OPTIMIZATION |
Afeta a otimização do intervalo | Tabela, índice |
QB_NAME |
Atribui um nome ao bloco de consulta | Bloqueio de consulta |
SEMIJOIN, NO_SEMIJOIN |
Afeta estratégias de semi-join | Bloqueio de consulta |
SUBQUERY |
Afeta a materialização, estratégias de subconsultas IN -para-EXISTS . |
Bloqueio de consulta |
As Dicas de índice do MySQL
fornecem ao otimizador informações sobre como escolher índices durante o processamento
da consulta. As palavras-chave USE
, FORCE
ou IGNORE
são usadas para controlar o processo de uso do índice do otimizador, por exemplo:
SELECT * FROM tbl USE INDEX (col1_index, col2_index);
-- OR
SELECT * FROM tbl IGNORE INDEX (col1_index, col2_index);
Observações sobre a conversão
Como há diferenças fundamentais entre o otimizador do MySQL e Oracle, e porque há limitação se houver sobreposição entre dicas de consulta MySQL e Oracle, recomendamos que você converta qualquer instrução SQL do Oracle que contenha dicas de consulta não especificadas sobre o banco de dados MySQL de destino.
Ajuste o desempenho do MySQL por meio das ferramentas do MySQL (por exemplo, Workbench do MySQL para painéis de desempenho em tempo real) e de recursos como análise de consultas usando planos de execução e ajuste dos parâmetros de instância ou sessão de acordo com o caso de uso.
Planos de execução
O principal objetivo dos planos de execução é fornecer uma visão interna das escolhas feitas pelo otimizador de consultas para acessar dados do banco de dados. O otimizador de consultas gera planos de execução para instruções SELECT
, INSERT
, UPDATE
e DELETE
para usuários de banco de dados, permitindo que os administradores tenham uma visão melhor de consultas específicas e operações DML. Elas são especialmente úteis quando você precisa fazer o ajuste de desempenho de consultas, por exemplo, para determinar o desempenho do índice ou para determinar se há índices ausentes que precisam ser criados.
Os planos de execução podem ser afetados por volumes de dados, estatísticas de dados e parâmetros de instância (parâmetros globais ou de sessão).
Considerações sobre conversão
Os planos de execução não são objetos de banco de dados que precisam ser migrados. Em vez disso, eles são uma ferramenta para analisar as diferenças de desempenho entre Oracle e MySQL executando a mesma instrução em conjuntos de dados idênticos.
O MySQL não é compatível com a mesma sintaxe, funcionalidade ou saída do plano de execução do Oracle.
Exemplos
Plano de execução do Oracle |
---|
SQL> EXPLAIN PLAN FOR SELECT * FROM EMPLOYEES WHERE EMPLOYEE_ID = 105; |
Plano de execução do MySQL |
mysql> EXPLAIN SELECT * FROM EMPLOYEES WHERE EMPLOYEE_ID = 105; |
Procedimentos, funções e gatilhos armazenados
PL/SQL é a linguagem processual estendida do Oracle usada para criar, armazenar e aplicar soluções baseadas em código no banco de dados. Em geral, os procedimentos e funções armazenados no banco de dados são elementos de código que consistem em linguagem processual estendida ANSI SQL e SQL, por exemplo, PL/SQL para Oracle, PL/pgSQL para PostgreSQL e linguagem processual MySQL para MySQL. O MySQL usa o mesmo nome do banco de dados para sua própria linguagem processual estendida.
O objetivo desses procedimentos e funções armazenados é fornecer soluções para requisitos mais adequados para execução no banco de dados e não no aplicativo (por exemplo, desempenho, compatibilidade e segurança). Ainda que os procedimentos e as funções armazenados usem PL/SQL, os procedimentos armazenados são usados principalmente para executar operações DDL/DML, e as funções são usadas principalmente para executar cálculos e retornar resultados específicos.
Linguagem processual PL/SQL para MySQL
Do ponto de vista da migração de código do Oracle PL/SQL para o MySQL, a implementação processual do MySQL é diferente da implementação do Oracle. Portanto, a migração de código é necessária para converter a funcionalidade PL/SQL do Oracle em procedimentos e funções armazenados no MySQL. Além disso, o pacote Oracle e o corpo do pacote não são compatíveis com o MySQL. Portanto, ao fazer a conversão de código, converta esses elementos (ou analise-os) em unidades únicas de código MySQL. Observe que os procedimentos e funções armazenados do MySQL também são chamados de routines.
Proprietário do objeto de código
No Oracle, o proprietário de um procedimento ou função armazenada é um usuário específico. No MySQL, o proprietário é um esquema específico (criado em um banco de dados por um usuário de banco de dados).
Privilégios e segurança do objeto de código
No Oracle, para criar um procedimento ou função armazenada, o usuário precisa ter o privilégio de sistema CREATE PROCEDURE
(para criar procedimentos ou funções em outros usuários diferentes, os usuários do banco de dados precisam ter o privilégio CREATE
ANY PROCEDURE
). Para executar um procedimento armazenado ou uma função, os usuários do banco de dados precisam ter o privilégio EXECUTE
.
No MySQL, para criar um elemento de código, o usuário precisa ter os privilégios CREATE
ROUTINE
e EXECUTE
para executar. A cláusula DEFINER
do MySQL define o criador do usuário para o objeto de código, e o usuário precisa ter os privilégios apropriados, como CREATE ROUTINE
.
Sintaxe de procedimento e função armazenados do MySQL
O exemplo a seguir mostra o procedimento armazenado do MySQL e a sintaxe (em inglês):
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