Este documento faz parte de uma série que fornece informações e orientações importantes relacionadas com o planeamento e a execução de migrações de bases 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 seguintes partes:
- Migrar utilizadores do Oracle para o Cloud SQL para MySQL: terminologia e funcionalidade
- Migrar utilizadores do Oracle para o Cloud SQL para MySQL: tipos de dados, utilizadores e tabelas
- Migrar utilizadores da Oracle para o Cloud SQL para MySQL: consultas, procedimentos armazenados, funções e acionadores (este documento)
- Migrar utilizadores do Oracle para o Cloud SQL para MySQL: segurança, operações, monitorização e registo
Consultas
O Oracle e o Cloud SQL para MySQL suportam a norma ANSI SQL. Geralmente, a migração de declarações SQL é simples quando usa apenas elementos de sintaxe básicos (por exemplo, não especificar funções escalares nem qualquer outra funcionalidade expandida do Oracle). A secção seguinte aborda os elementos de consulta Oracle comuns e os respetivos equivalentes do Cloud SQL para MySQL.
Sintaxe básica SELECT e FROM
Nome da funcionalidade ou nome da sintaxe da Oracle | Vista geral ou implementação da Oracle | Suporte do MySQL | Solução correspondente ou alternativa do MySQL |
---|---|---|---|
Sintaxe básica de SQL para obtençã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 |
Alias de colunas | SELECT COL1 AS C1 |
Sim | SELECT COL1 AS C1 OR SELECT COL1 C1 |
Nome da tabela sensibilidade a maiúsculas e minúsculas |
Sem sensibilidade a maiúsculas e minúsculas (por exemplo, o nome da tabela pode ser orders
e/ou ORDERS ). |
Não | Sensível a maiúsculas e minúsculas de acordo com o nome da tabela definido (por exemplo, o nome da tabela só pode ser orders ou ORDERS ). |
Pode ler mais detalhes sobre a sintaxe SELECT
do MySQL.
- Visualizações incorporadas
- As vistas em linha (também conhecidas como tabelas derivadas) são declarações
SELECT
localizadas na cláusulaFROM
e usadas como uma subconsulta. - As vistas incorporadas podem ajudar a simplificar consultas complexas removendo cálculos compostos ou eliminando operações de junção, ao mesmo tempo que condensam várias consultas separadas numa única consulta simplificada.
- Nota de conversão: as visualizações inline do Oracle não requerem a utilização de alias, enquanto o MySQL requer alias específicos para cada visualização inline.
- As vistas em linha (também conhecidas como tabelas derivadas) são declarações
A tabela seguinte apresenta um exemplo de conversão do Oracle para o MySQL, como uma vista inline.
Oracle 11g/12c |
---|
SQL> SELECT FIRST_NAME, DEPARTMENT_ID, SALARY, DATE_COL FROM EMPLOYEES, (SELECT SYSDATE AS DATE_COL FROM DUAL); O resultado é semelhante ao seguinte: 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 vista inline:mysql> SELECT FIRST_NAME, DEPARTMENT_ID, SALARY, DATE_COL FROM EMPLOYEES, (SELECT SYSDATE() AS DATE_COL FROM DUAL); Adicionar um alias à vista inline: mysql> SELECT FIRST_NAME, DEPARTMENT_ID, SALARY, DATE_COL FROM EMPLOYEES, (SELECT SYSDATE() AS DATE_COL FROM DUAL) AS A1; O resultado é semelhante ao seguinte: +-------------+---------------+----------+---------------------+ | 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 | |
Declarações JOIN
As declarações JOIN
do Oracle são suportadas pelas declarações JOIN
do MySQL, exceto pela cláusula FULL JOIN
. Além disso, as declarações JOIN
do MySQL suportam a utilização de sintaxe alternativa, como a cláusula USING
, a cláusula WHERE
em vez da cláusula ON
e a utilização de SUBQUERY
na declaração JOIN
.
A tabela seguinte apresenta um exemplo de conversão de JOIN.
Tipo de JOIN da Oracle | Suportado pelo MySQL | Sintaxe 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 contornar o problema, considere usar UNION com declaraçõ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 suporta 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 declaraçõesSELECT
e elimina os registos duplicados.UNION ALL
: anexa os conjuntos de resultados de duas ou mais declaraçõesSELECT
sem eliminar registos duplicados.INTERSECT
: devolve a interseção de duas ou mais declaraçõesSELECT
apenas se existir um registo em ambos os conjuntos de dados.MINUS
: compara duas ou mais declaraçõesSELECT
, devolvendo apenas linhas distintas da primeira consulta que não são devolvidas pelas outras declarações.
Notas de conversão
Quando converter funções Oracle INTERSECT
e MINUS
em MySQL, use declarações JOIN
e IN
e EXISTS
como solução alternativa.
Exemplos
Função Oracle | Implementação da Oracle | Suporte do MySQL | Solução correspondente ou alternativa 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 oferece uma lista extensa de funções escalares (de linha única) e de agregação. Algumas funções do MySQL são semelhantes às suas equivalentes do Oracle (pelo nome e funcionalidade ou com um nome diferente, mas com uma funcionalidade semelhante). Embora as funções do MySQL possam ter nomes idênticos aos das funções equivalentes do Oracle, podem apresentar uma funcionalidade diferente.
As tabelas seguintes descrevem onde o Oracle e o MySQL são equivalentes por nome e funcionalidade (especificado por "Sim") e onde é recomendada uma conversão (todos os casos que não sejam "Sim").
Funções de carateres
Função Oracle | Especificação ou implementação da função Oracle | Equivalente do MySQL | Função correspondente do MySQL | Especificação ou implementação da função MySQL |
---|---|---|---|---|
CONCAT(str1,str2) |
Devolve str1 concatenado com str2:CONCAT('A', 1) = A1 |
Sim | CONCAT |
Equivalente a Oracle:CONCAT('A', 1) = A1 |
LOWER/UPPER |
Devolve char com todas as letras em minúsculas ou maiúsculas:LOWER('SQL') = sql |
Sim | LOWER/UPPER |
Equivalente a Oracle:LOWER('SQL') = sql |
LPAD/RPAD(expr1,n,expr2) |
Devolve expr1, com preenchimento à esquerda ou à direita até ao comprimento de n carateres
com a sequência de carateres em expr2:LPAD('A',3,'*') = **A |
Sim | LPAD/RPAD |
Equivalente a Oracle:LPAD('A',3,'*') = **A |
SUBSTR(char,p,n) |
Devolve uma parte de char, começando na posição do caráter p, com um comprimento de substring de n carateres:SUBSTR('MySQL', 3, 3) = SQL |
Sim | SUBSTR(char,p,n) |
Equivalente a Oracle:SUBSTR('MySQL', 3, 3) = SQL |
INSTR(index,str) |
Devolve a posição (index) da string str:INSTR('MySQL', 'y') = 2 |
Sim | INSTR |
Equivalente a Oracle:INSTR('MySQL', 'y') = 2 |
REPLACE(char,str1,str2) |
Devolve o carater com todas as ocorrências de uma string de pesquisa substituídas por uma string de substituição: REPLACE('ORADB', 'ORA', 'MySQL') |
Sim | REPLACE(char,str1,str2) |
Equivalente a Oracle:REPLACE('ORADB', 'ORA', 'MySQL') |
TRIM(str) |
Remova carateres à esquerda ou à direita (ou ambos) de uma string:TRIM(both '-' FROM '-MySQL-') = MySQL |
Sim | TRIM(str) |
Equivalente a Oracle:TRIM(both '-' FROM '-MySQL-') = MySQL |
LTRIM/RTRIM(str) |
Remove do início ou do fim da string todos os carateres que
aparecem na pesquisa:LTRIM(' MySQL', ' ') = MySQL |
Parcialmente | LTRIM/RTRIM(str) |
Função R/LTRIM da Oracle, exceto uma substituição do parâmetro (espaço em branco ou string). O MySQL R/LTRIM só elimina os espaços em branco, aceitando apenas a string de entrada:LTRIM(' MySQL') = MySQL |
ASCII(char) |
Devolve a representação decimal no conjunto de carateres da base de dados do primeiro caráter de char: ASCII('A') = 65 |
Sim | ASCII(char) |
Equivalente a Oracle:ASCII('A') = 65 |
CHR(char) |
Devolve o valor do código ASCII, que é um valor numérico entre 0 e 225,
para um caráter:CHR(65) = A |
Parcialmente com um nome de função diferente | CHAR(char) |
O MySQL usa a função CHAR para a mesma funcionalidade. Por isso, tem de modificar um nome de função:CHAR(65) = A |
LENGTH(str) |
Devolver o comprimento de uma determinada string:LENGTH ('MySQL') = 5 |
Sim | LENGTH(str) |
Equivalente a Oracle:LENGTH('MySQL') = 5 |
REGEXP_REPLACE(str1,expr,str2) |
Pesquise uma string por um padrão de expressão regular:REGEXP_REPLACE('John', '[hn].', '1') = Jo1 |
Não | N/A | Apenas suportado a partir da versão 8 do MySQL. Como solução alternativa, use a função REPLACE , se possível, ou converta para a camada de aplicação |
REGEXP_SUBSTR(str,expr) |
Expande a funcionalidade da função SUBSTR pesquisando uma string por um padrão de expressão regular:REGEXP_SUBSTR('https://console.cloud.google.com/sql/instances','https://([[:alnum:]]+\.?){3,4}/?') = https://console.cloud.google.com/ |
Não | N/A | Apenas suportado a partir da versão 8 do MySQL. Para uma solução alternativa, use a função SUBSTR , se possível, ou converta a funcionalidade na camada de aplicação. |
REGEXP_COUNT(str,expr) |
Devolve o número de vezes que um padrão ocorre numa string de origem. | Não | N/A | Para uma solução alternativa, converta a funcionalidade para a camada de aplicação. |
REGEXP_INSTR(index,expr) |
Pesquise uma posição (índice) de string para um padrão de expressão regular. | Não | N/A | Apenas suportado a partir da versão 8 do MySQL. |
REVERSE(str) |
Devolva uma string invertidaREVERSE('MySQL') = LQSyM |
Sim | REVERSE |
Equivalente a Oracle:REVERSE('MySQL') = LQSyM |
Funções numéricas
Função Oracle | Especificação ou implementação da função Oracle | Equivalente do MySQL | Função correspondente do MySQL | Especificação ou implementação da função MySQL |
---|---|---|---|---|
ABS(n) |
Valor absoluto de n: ABS(-4.6) = 4.6 |
Sim | ABS |
Equivalente a Oracle:ABS(-4.6) = 4.6 |
CEIL(n) |
Devolve o menor número inteiro que é maior ou igual a n:CEIL(21.4) = 22 |
Sim | CEIL |
Equivalente a Oracle:CEIL(21.4) = 22 |
FLOOR(n) |
Devolve o maior número inteiro igual ou inferior a n: FLOOR(-23.7) = -24 |
Sim | FLOOR |
Equivalente a Oracle:FLOOR(-23.7) = -24 |
MOD(m,n) |
Devolve o resto de m dividido por n:MOD(10, 3) = 1 |
Sim | MOD(m,n) |
Equivalente a Oracle:MOD(10,3) = 1 |
ROUND(m,n) |
Devolve m arredondado a n casas decimais à direita da vírgula decimal:ROUND(1.39,1) = 1.4 |
Sim | ROUND |
Equivalente a Oracle:ROUND(1.39,1) = 1.4 |
TRUNC(n1, n2) |
Devolve n1 truncado para n2 casas decimais:TRUNC(99.999) = 99 TRUNC(99.999,0) = 99 |
Parcialmente com um nome de função diferente | TRUNCATE(n1, n2) |
A função TRUNCATE do MySQL tem de aceitar um número de entrada e um número inteiro para especificar a quantidade 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 Oracle | Equivalente do MySQL | Função correspondente do MySQL | Especificação ou implementação da função MySQL |
---|---|---|---|---|
SYSDATE |
Devolve a data e a hora atuais definidas para o sistema operativo no qual o servidor de base de dados reside:SELECT SYSDATE FROM DUAL = 31-JUL-2019 |
Parcialmente | SYSDATE() |
O MySQL SYSDATE() tem de incluir parênteses e devolve um formato de data/hora diferente da função Oracle SYSDATE :SELECT SYSDATE() FROM DUAL; = 2019-01-31 10:01:01.0 Tenha em atenção que a formatação de data/hora pode ser alterada ao nível da sessão |
SYSTIMESTAMP |
Devolve a data do sistema, incluindo frações de segundos e o fuso horário:SELECT SYSTIMESTAMP FROM DUAL = 01-JAN-19 07.37.11.622187000 AM +00:00 |
Parcialmente com um nome de função diferente | CURRENT_TIMESTAMP |
O MySQL devolve uma formatação de data/hora diferente da do Oracle. É necessária uma formatação de data (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 |
Devolve a data e hora atuais no fuso horário da sessão num valor do tipo de dados TIMESTAMP :SELECT LOCAL_TIMESTAMP FROM DUAL = 01-JAN-19 10.01.10.123456 PM |
Parcialmente com uma formatação de data/hora diferente. | LOCAL_TIMESTAMP |
O MySQL devolve uma formatação de data/hora diferente da do Oracle. A formatação de data/hora é necessá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 |
Devolve 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 devolve uma formatação de data/hora diferente da do Oracle. A formatação de data/hora é necessá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 |
Devolve a data e 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 devolve uma formatação de data/hora diferente da do Oracle. A formatação de data/hora é necessária (ou usar 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 |
Devolve a data mais um número inteiro de meses:ADD_MONTHS(SYSDATE, 1) = 31-JAN-19 |
Parcialmente com um nome de função diferente | ADDDATE |
Para alcançar a mesma funcionalidade, o MySQL usa a função ADDDATE :ADDDATE(SYSDATE(), 1) = 2019-08-01 06:42:49.0 Por predefinição, o MySQL devolve uma data/hora e um intervalo/formato diferentes dos do Oracle. A formatação de data/hora é necessária (ou uma função de data diferente) para corresponder à formatação de data/hora original. |
EXTRACT (date part) |
Devolve o valor de um campo de data/hora especificado a partir de uma expressão de data/hora ou de intervalo:EXTRACT(YEAR FROM DATE '2019-01-31') = 2019 |
Sim | EXTRACT (date part) |
Equivalente a Oracle:EXTRACT(YEAR FROM DATE '2019-01-31') = 2019 |
LAST_DAY |
Devolve 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 devolve uma formatação de data/hora diferente da do Oracle. A formatação de data/hora é necessá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 |
Devolve o número de meses entre as datas date1 e date2:MONTHS_BETWEEN( SYSDATE, SYSDATE-60) = 1.96 |
Parcialmente com um nome de função diferente | PERIOD_DIFF(date1,date2) |
A função PERIOD_DIFF do MySQL devolve a diferença em meses como um número inteiro entre dois períodos (formatados como YYMM ou YYYYMM ):PERIOD_DIFF( '201903', '201901') = 2 Para alcançar os mesmos valores que a função MONTH_BETWEEN do Oracle, é necessária uma conversão mais específica |
TO_CHAR (data/hora) |
Converte um tipo de dados de data/hora ou indicação de tempo num valor do 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 um 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 descodificação
Função Oracle | Especificação ou implementação da função Oracle | Equivalente do MySQL | Função correspondente do MySQL | Especificação ou implementação da função MySQL |
---|---|---|---|---|
DECODE |
Compara a expressão com cada valor de pesquisa um a um através da funcionalidade de uma declaração IF-THEN-ELSE |
Não | CASE |
Use a declaração CASE do MySQL para alcançar uma funcionalidade semelhante. |
DUMP |
Devolve 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 | Não suportado. |
ORA_HASH |
Calcula um valor de hash para uma determinada expressão. | Não | MD5/SHA |
Use o MySQL MD5 para a soma de verificação de 128 bits ou a função SHA
para a soma de verificação de 160 bits para gerar valores hash |
Funções de conversão
Função Oracle | Especificação ou implementação da função Oracle | Equivalente do MySQL | Função correspondente do MySQL | Especificação ou implementação da função MySQL |
---|---|---|---|---|
CAST |
Converte um tipo de dados incorporado ou um valor de tipo de coleção noutro tipo de dados incorporado ou valor de tipo de coleção: CAST('1' as int) + 1 = 2 |
Parcialmente | CAST |
A função CAST do MySQL é semelhante à funcionalidade do Oracle, mas, em determinados casos, tem de ser ajustada consoante seja necessária uma conversão explícita ou implícita:CAST('1' AS SIGNED) + 1 = 2 |
CONVERT |
Converte uma string de carateres de um conjunto de carateres para outro: CONVERT('Ä Ê Í Õ Ø A B C D E ', 'US7ASCII', 'WE8ISO8859P1') = ?? ?? ?? A B C |
Parcialmente | CONVERT |
A função CONVERT do MySQL requer alguns ajustes à sintaxe e aos parâmetros para devolver os resultados exatos como o 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 numa string: TO_CHAR(22.73,'$99.9') = $22.7 |
Não | FORMAT |
A função FORMAT do MySQL executa formatos de "#,###.##" a partir de um número, arredondando-o para um determinado número de casas decimais e, em seguida, devolve o resultado como uma string. Tem uma funcionalidade diferente da do Oracle:CONCAT('$', FORMAT(22.73, 1)) = $22.7 |
TO_DATE |
A função TO_DATE do Oracle converte uma string numa data através do formato de data/hora específico da origem:TO_DATE( '2019/01/01', 'yyyy-mm-dd') = 01-JAN-2019 |
Parcialmente com um nome de função e uma formatação de data/hora diferentes | STR_TO_DATE |
A função STR_TO_DATE do MySQL usa uma string e devolve 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 num valor de um tipo de dados NUMBER :TO_NUMBER('01234') = 1234 |
Não | CAST |
Em alternativa, use a função CAST do MySQL para devolver o mesmo resultado que a função TO_NUMBER do Oracle:CAST('01234' as SIGNED) = 1234 |
Funções SELECT condicionais
Função Oracle | Especificação ou implementação da função Oracle | Equivalente do MySQL | Função correspondente do MySQL | Especificação ou implementação da função MySQL |
---|---|---|---|---|
CASE |
A declaração CASE escolhe a partir de uma sequência de condições e executa uma declaraçã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 suporta a utilização do processamento condicional IF/ELSE na declaraçã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 Oracle | Equivalente do MySQL | Função correspondente do MySQL | Especificação ou implementação da função MySQL |
---|---|---|---|---|
COALESCE |
Devolve a primeira expressão não nula na lista de expressões: COALESCE( null, '1', 'a') = a |
Sim | COALESCE |
Equivalente a Oracle:COALESCE( null, '1', 'a') = 1 |
NULLIF |
Compare expr1 e expr2m. Se forem iguais, a função devolve nulo. Se não forem iguais, a função devolve expr1: NULLIF('1', '2') = a |
Sim | NULLIF |
Equivalente a Oracle:NULLIF('1', '2') = a |
NVL |
Substitua o valor nulo (devolvido como um espaço 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 os valores nulos por uma string especificada:IFNULL(null, 'a') = a |
NVL2 |
Determinar o valor devolvido por uma consulta com base no facto de uma expressão especificada ser nula ou não nula. |
Não | CASE |
A declaração CASE escolhe a partir de uma sequência de condições e executa uma declaração correspondente: CASE WHEN condition THEN result [WHEN ...] [ELSE result] END |
Funções de ambiente e identificadores
Função Oracle | Especificação ou implementação da função Oracle | Equivalente do MySQL | Função correspondente do MySQL | Especificação ou implementação da função MySQL |
---|---|---|---|---|
SYS_GUID |
Gera e devolve um identificador único global (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 |
Devolve um número inteiro que identifica exclusivamente o utilizador da sessão (o utilizador que iniciou sessão): SELECT UID FROM DUAL = 43 |
Não | N/A | N/A |
USER |
Devolve o nome de utilizador da sessão atual:SELECT USER FROM DUAL = UserName |
Parcialmente | USER + INSTR + SUBSTR |
A função USER do MySQL devolve o nome de utilizador juntamente com o servidor de ligação (root@IP ). Para obter apenas o nome de utilizador, use funções de apoio adicionais:SELECT SUBSTR(USER(), 1, INSTR(USER(), '@') -1) FROM DUAL = root |
USERENV |
Devolve informações sobre a sessão do utilizador atual com a configuração de parâmetros atual:SELECT USERENV('LANGUAGE') FROM DUAL = ENGLISH_AMERICA.AL32UTF8 |
Não | SHOW SESSION VARIABLES |
Use a declaração SHOW SESSION VARIABLES do MySQL para ver as definições da sessão atual:SHOW SESSION VARIABLES LIKE '%collation%'; = utf8_general_ci |
ROWID |
O servidor Oracle atribui a cada linha de cada tabela um número único
ROWID 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 ficheiro de dados. |
Não | N/A | Se possível, tente emular a mesma funcionalidade com outras funções do MySQL. |
ROWNUM |
Devolve um número que representa a ordem pela qual uma linha é selecionada pelo Oracle a partir de uma tabela ou de tabelas unidas. | 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 da função Oracle ou implementação |
MySQL equivalente |
Função correspondente do MySQL | Especificação ou implementação da função MySQL |
---|---|---|---|---|
AVG |
Devolve o valor médio da coluna ou da expressão. | Sim | AVG |
Equivalente a Oracle |
COUNT |
Devolve o número de linhas devolvidas por uma consulta. | Sim | COUNT |
Equivalente a Oracle |
COUNT (DISTINCT) |
Devolve o número de valores únicos na coluna ou expressão. | Sim | COUNT (DISTINCT) |
Equivalente a Oracle |
MAX |
Devolve o valor máximo da coluna ou da expressão. | Sim | MAX |
Equivalente a Oracle |
MIN |
Devolve o valor mínimo da coluna ou da expressão. | Sim | MIN |
Equivalente a Oracle |
SUM |
Devolve a soma do valor da coluna ou da expressão. | Sim | SUM |
Equivalente a Oracle |
LISTAGG |
Apresenta os dados em cada grupo por uma única linha especificada na cláusula ORDER BY , concatenando os valores da coluna de métricas: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 devolver resultados semelhantes aos do Oracle,
exceto diferenças de sintaxe em determinados casos:SELECT GROUP_CONCAT( DEPARTMENT_NAME ORDER BY DEPARTMENT_NAME SEPARATOR ', ') DEPT FROM DEPARTMENTS; |
Oracle 12c Fetch
Função Oracle | Especificação da função Oracle ou implementação |
MySQL equivalente |
Função correspondente do MySQL | Especificação ou implementação da função MySQL |
---|---|---|---|---|
FETCH |
Obtém 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 obter apenas um conjunto específico de registos:SELECT * FROM EMPLOYEES LIMIT 10; |
Filtragem básica, operadores e subconsultas
Durante a conversão, a filtragem básica, as funções de operador e as subconsultas são relativamente simples e requerem pouco ou nenhum esforço adicional.
Notas de conversão
Examine e resolva os formatos de data, porque os formatos Oracle e MySQL devolvem resultados predefinidos diferentes:
- Por predefinição, a função
SYSDATE
Oracle01-AUG-19
devolve01-AUG-19
. - Por predefinição, a função
SYSDATE()
do MySQL devolve2019-08-01 12:04:05
. - Os formatos de data e hora podem ser definidos através das funções MySQL
[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)
.
Função ou subconsulta Oracle | Equivalente do MySQL | Função ou subconsulta correspondente do MySQL | Especificação ou implementação da função 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 suporta subconsultas ao nível de SELECT , para declaraçõ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 suporta todos os operadores básicos:> | >= | < | <= | = | <> | != |
Funções analíticas (ou funções de janela e classificação)
As funções analíticas da Oracle expandem a funcionalidade das funções analíticas SQL padrão, oferecendo capacidades para calcular valores agregados com base num grupo de linhas. Estas funções podem ser aplicadas a conjuntos de resultados logicamente particionados no âmbito de uma única expressão de consulta. Normalmente, são usadas em combinação com relatórios e estatísticas de Business Intelligence, com o potencial de aumentar o desempenho das consultas como alternativa para alcançar o mesmo resultado usando código SQL não analítico mais complexo.
Notas de conversão
- A versão 5.7 do MySQL não fornece funções analíticas para suportar uma conversão simples de declarações SQL. No entanto, esta funcionalidade foi adicionada parcialmente na versão 8 do MySQL, o que faz da conversão de funções analíticas um ponto a considerar, que provavelmente requer esforço manual no processo de migração.
- Uma solução opcional é reescrever o código para remover a utilização de funções analíticas, revertendo para soluções de código SQL mais tradicionais ou movendo esta lógica para uma camada de aplicação.
A tabela seguinte lista as funções analíticas comuns da Oracle.
Família de funções | Funções relacionadas | Suportado pelo 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)
As CTEs oferecem uma forma de implementar a lógica de código sequencial para reutilizar código SQL que pode ser demasiado complexo ou não eficiente para utilização múltipla. As CTEs podem ser nomeadas e, em seguida, usadas várias vezes em diferentes partes de uma declaração SQL através da cláusula WITH
.
Notas de conversão
- A versão 5.7 do MySQL não suporta CTEs, mas a versão 8 do MySQL suporta.
- Para uma solução alternativa, use tabelas derivadas ou subconsultas, ou reescreva a declaração SQL para eliminar a funcionalidade 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 declaração MERGE
(ou UPSERT
) oferece um meio de especificar declarações SQL únicas que realizam condicionalmente operações DML numa operação MERGE
, em oposição a uma única operação DML, executada separadamente. Seleciona registos da tabela de origem e, em seguida, especificando uma estrutura lógica, executa automaticamente várias operações DML na tabela de destino. Esta funcionalidade ajuda a evitar a utilização de várias inserções, atualizações ou eliminações. Tenha em atenção que MERGE
é uma declaração determinística, o que significa que, depois de uma linha ser processada pela declaração MERGE
, não pode ser processada novamente com a mesma declaração MERGE
.
Notas de conversão
A versão 5.7 do MySQL não suporta a funcionalidade MERGE
, ao contrário do Oracle. Para simular parcialmente a funcionalidade MERGE
, o MySQL fornece as declarações REPLACE
e INSERT… ON DUPLICATE KEY UPDATE
:
REPLACE
: funciona da mesma forma que uma declaraçãoINSERT
, exceto se uma linha antiga na tabela tiver o mesmo valor que uma nova linha para um índicePRIMARY KEY
ouUNIQUE
. Nesse caso, a linha antiga é eliminada antes de a nova linha ser inserida.INSERT… ON DUPLICATE KEY UPDATE
: se uma linha inserida causar um valor duplicado num índicePRIMARY KEY
ouUNIQUE
, ocorre umaUPDATE
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
num procedimento armazenado para gerir operações DML, usando comandos INSERT
, UPDATE
e DELETE
com processamento de exceções e duplicações.
Instruções de declarações SQL
A Oracle oferece uma grande coleção de sugestões de consultas SQL que permitem aos utilizadores influenciar o comportamento do otimizador e a respetiva tomada de decisões, com o objetivo de produzir planos de execução de consultas mais eficientes. A Oracle suporta mais de 60 sugestões de bases de dados diferentes. O MySQL oferece um conjunto limitado de sugestões de consultas.
Em geral, a versão 5.7 do MySQL suporta dois tipos de sugestões de consultas: OPTIMIZER
HINTS
e INDEX HINTS
.
As sugestões do otimizador do MySQL oferecem a capacidade de controlar o comportamento do otimizador em declarações SQL individuais, por exemplo:
SELECT /*+ NO_RANGE_OPTIMIZATION(tbl PRIMARY, col1_idx) */ col1 FROM tbl;
Versão 5.7 do MySQL Sugestões do otimizador disponíveis
Nome da sugestão | Vista geral das sugestões | Âmbitos aplicáveis |
---|---|---|
BKA, NO_BKA |
Afeta o processamento de junções de acesso de chaves em lote | Bloco de consultas, tabela |
BNL, NO_BNL |
Afeta o processamento de junções de ciclo aninhado de blocos | Bloco de consultas, tabela |
MAX_EXECUTION_TIME |
Limita o tempo de execução da declaração | Global |
MRR, NO_MRR |
Afeta a otimização de leitura de vários intervalos | Tabela, índice |
NO_ICP |
Afeta a otimização de pushdown da condição de índice | Tabela, índice |
NO_RANGE_OPTIMIZATION |
Afeta a otimização do intervalo | Tabela, índice |
QB_NAME |
Atribui um nome ao bloco de consultas | Bloco de consultas |
SEMIJOIN, NO_SEMIJOIN |
Afeta as estratégias de junção parcial | Bloco de consultas |
SUBQUERY |
Afeta a materialização das estratégias de subconsulta de IN para EXISTS . |
Bloco de consultas |
As sugestões de índice do MySQL fornecem ao otimizador informações sobre como escolher índices durante o processamento de consultas. As palavras-chave USE
, FORCE
ou IGNORE
são usadas para controlar o processo de utilização 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);
Notas de conversão
Como existem diferenças fundamentais entre o otimizador do Oracle e do MySQL e, como existem poucas ou nenhumas sobreposições entre as sugestões de consultas do Oracle e do MySQL, recomendamos que converta qualquer declaração SQL do Oracle que contenha sugestões de consultas não especificadas na base de dados MySQL de destino.
Faça o ajuste de desempenho do MySQL através de ferramentas do MySQL (por exemplo, o MySQL Workbench para painéis de controlo de desempenho em tempo real) e funcionalidades como examinar consultas usando planos de execução e ajustar os parâmetros da instância ou da sessão de acordo com o exemplo de utilização.
Planos de execução
O objetivo principal dos planos de execução é fornecer uma análise detalhada das escolhas feitas pelo otimizador de consultas para aceder aos dados da base de dados. O otimizador de consultas gera planos de execução para declarações SELECT
, INSERT
, UPDATE
e DELETE
para utilizadores da base de dados, o que também permite aos administradores ter uma melhor vista das consultas específicas e das operações DML. São especialmente úteis quando
precisa de otimizar o desempenho das consultas, por exemplo, para determinar o desempenho
dos índices ou determinar se existem índices em falta que precisam de ser
criados.
Os planos de execução podem ser afetados pelos volumes de dados, pelas estatísticas de dados e pelos parâmetros de instâncias (parâmetros globais ou de sessão).
Considerações sobre as conversões
Os planos de execução não são objetos de base de dados que precisam de ser migrados. Em alternativa, são uma ferramenta para analisar as diferenças de desempenho entre o Oracle e o MySQL que executam a mesma declaração em conjuntos de dados idênticos.
O MySQL não suporta a mesma sintaxe, funcionalidade nem resultado do plano de execução que o Oracle.
Exemplos
Plano de execução da 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 armazenados, funções e acionadores
O PL/SQL é a linguagem processual expandida da Oracle usada para criar, armazenar e aplicar soluções baseadas em código na base de dados. Em geral, os procedimentos e as funções armazenados na base de dados são elementos de código que consistem em ANSI SQL e linguagem processual estendida de SQL, por exemplo, PL/SQL para Oracle, PL/pgSQL para PostgreSQL e linguagem processual de MySQL para MySQL. O MySQL usa o mesmo nome que a base de dados para o seu próprio idioma processual expandido.
O objetivo destes procedimentos e funções armazenados é fornecer soluções para requisitos mais adequados para execução a partir da base de dados e não da aplicação (por exemplo, desempenho, compatibilidade e segurança). Embora os procedimentos e as funções armazenados usem PL/SQL, os procedimentos armazenados são usados principalmente para realizar operações DDL/DML e as funções são usadas principalmente para realizar cálculos para devolver resultados específicos.
PL/SQL para linguagem procedural 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 do Oracle. Por conseguinte, é necessária a migração de código para converter a funcionalidade PL/SQL do Oracle em funções e procedimentos armazenados do MySQL. Além disso, o Oracle Package e o Package Body não são suportados pelo MySQL. Por isso, quando fizer a conversão de código, converta estes elementos (ou analise-os) em unidades únicas de código MySQL. Tenha em atenção que os procedimentos armazenados e as funções do MySQL também são denominados rotinas.
Proprietário do objeto de código
No Oracle, o proprietário de um procedimento ou uma função armazenada é um utilizador específico. No MySQL, o proprietário é um esquema específico (criado numa base de dados por um utilizador da base de dados).
Privilégios e segurança de objetos de código
No Oracle, para criar um procedimento ou uma função armazenada, o utilizador tem de ter o privilégio do sistema CREATE PROCEDURE
(para criar procedimentos ou funções sob outros utilizadores diferentes, os utilizadores da base de dados têm de ter o privilégio CREATE
ANY PROCEDURE
). Para executar um procedimento armazenado ou uma função, os utilizadores da base de dados têm de ter o privilégio EXECUTE
.
No MySQL, para criar um elemento de código, o utilizador tem de ter o privilégio CREATE
ROUTINE
e o privilégio EXECUTE
para executar. A cláusula DEFINER
MySQL define o criador do utilizador para o objeto de código, e o utilizador tem de ter os privilégios adequados, como CREATE ROUTINE
.
Sintaxe de funções e procedimentos armazenados do MySQL
O exemplo seguinte mostra a sintaxe da função e do procedimento armazenado do 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