Ce document fait partie d'une série qui fournit des informations et des conseils clés sur la planification et l'exécution des migrations de base de données Oracle® 11g/12c vers des instances Cloud SQL pour MySQL de deuxième génération, version 5.7. La série comprend les parties suivantes :
- Migrer des utilisateurs Oracle vers Cloud SQL pour MySQL : terminologie et fonctionnalités
- Migrer des utilisateurs Oracle vers Cloud SQL pour MySQL : types de données, utilisateurs et tables
- Migrer des utilisateurs Oracle vers Cloud SQL pour MySQL : requêtes, procédures stockées, fonctions et déclencheurs (ce document)
- Migrer des utilisateurs Oracle vers Cloud SQL pour MySQL : sécurité, opérations, surveillance et journalisation
Requêtes
Oracle et Cloud SQL pour MySQL sont compatibles avec la norme ANSI SQL. Il est généralement facile de migrer des instructions SQL en n'utilisant que des éléments de syntaxe de base (par exemple, sans spécifier de fonctions scalaires ni aucune autre fonctionnalité Oracle étendue). La section suivante aborde les éléments de requête Oracle courants et leurs équivalents dans Cloud SQL pour MySQL.
Syntaxe SELECT et FROM de base
Nom de la fonctionnalité ou syntaxe Oracle | Présentation ou mise en œuvre dans Oracle | Compatibilité avec MySQL | Solution MySQL correspondante ou alternative |
---|---|---|---|
Syntaxe SQL de base pour la récupération de données | SELECT FROM WHERE GROUP BY HAVING ORDER BY |
Oui | SELECT FROM WHERE GROUP BY HAVING ORDER BY |
SELECT pour l'impression en sortie |
SELECT 1 FROM DUAL |
Oui | SELECT 1 OR SELECT 1 FROM DUAL |
Alias de colonne | SELECT COL1 AS C1 |
Oui | SELECT COL1 AS C1 OR SELECT COL1 C1 |
Nom de la table Sensibilité à la casse |
Pas de sensibilité à la casse (par exemple, le nom de la table peut être orders et/ou ORDERS ). |
Non | Sensibilité à la casse en fonction du nom de table défini (par exemple, le nom de la table ne peut être que orders ou ORDERS ). |
Apprenez-en davantage sur la syntaxe SELECT
de MySQL.
- Vues intégrées
- Les vues intégrées (également appelées tables dérivées) sont des instructions
SELECT
, situées dans la clauseFROM
et utilisées en tant que sous-requêtes. - Les vues intégrées peuvent simplifier les requêtes complexes en supprimant les calculs composés ou en éliminant les opérations de jointure, tout en regroupant plusieurs requêtes distinctes en une seule requête simplifiée.
- Remarque relative aux conversions : Les vues intégrées Oracle ne nécessitent pas l'utilisation d'alias, tandis que MySQL requiert l'utilisation d'alias spécifiques pour chaque vue intégrée.
- Les vues intégrées (également appelées tables dérivées) sont des instructions
Le tableau suivant présente un exemple de conversion d'Oracle vers MySQL, sous la forme d'une vue intégrée.
Oracle 11g/12c |
---|
SQL> SELECT FIRST_NAME, DEPARTMENT_ID, SALARY, DATE_COL FROM EMPLOYEES, (SELECT SYSDATE AS DATE_COL FROM DUAL); Le résultat ressemble à ce qui suit : 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 pour MySQL 5.7 |
Sans alias pour la vue intégrée :mysql> SELECT FIRST_NAME, DEPARTMENT_ID, SALARY, DATE_COL FROM EMPLOYEES, (SELECT SYSDATE() AS DATE_COL FROM DUAL); Ajout d'un alias à la vue intégrée : mysql> SELECT FIRST_NAME, DEPARTMENT_ID, SALARY, DATE_COL FROM EMPLOYEES, (SELECT SYSDATE() AS DATE_COL FROM DUAL) AS A1; Le résultat ressemble à ce qui suit : +-------------+---------------+----------+---------------------+ | 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 | |
Instructions JOIN
Les instructions Oracle JOIN
sont compatibles avec les instructions MySQL JOIN
, à l'exception de la clause FULL JOIN
. En outre, les instructions MySQL JOIN
acceptent l'utilisation d'une syntaxe alternative, telle que la clause USING
, la clause WHERE
au lieu de la clause ON
, ainsi que l'utilisation de SUBQUERY
dans l'instruction JOIN
.
Le tableau suivant présente un exemple de conversion JOIN.
Type d'instruction JOIN Oracle | Compatible avec MySQL | Syntaxe JOIN MySQL |
---|---|---|
INNER JOIN |
Oui | SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E JOIN DEPARTMENTS D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID; |
CROSS JOIN |
Oui | SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E CROSS JOIN DEPARTMENTS D |
FULL JOIN |
Non | Pour contourner ce problème, envisagez d'utiliser UNION avec les instructions LEFT et RIGHT JOIN . |
LEFT JOIN [ OUTER ] |
Oui | SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E LEFT JOIN DEPARTMENTS D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID; |
RIGHT JOIN [ OUTER ] |
Oui | SELECT E.FIRST_NAME, D.DEPARTMENT_NAME FROM EMPLOYEES E RIGHT JOIN DEPARTMENTS D ON E.DEPARTMENT_ID = D.DEPARTMENT_ID; |
SUBQUERY |
Oui | 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 et MINUS
MySQL n'est pas compatible avec les fonctions INTERSECT
et MINUS
Oracle, à l'exception des fonctions UNION
et UNION ALL
:
UNION
: joint les ensembles de résultats d'au moins deux instructionsSELECT
et supprime les enregistrements en double.UNION ALL
: joint les ensembles de résultats d'au moins deux instructionsSELECT
sans éliminer les enregistrements en double.INTERSECT
: renvoie l'intersection de deux instructionsSELECT
ou plus uniquement si un enregistrement existe dans les deux ensembles de données.MINUS
: compare deux ou plusieurs instructionsSELECT
, et ne renvoie que des lignes distinctes de la première requête qui ne sont pas renvoyées par les autres instructions.
Notes de conversion
Lorsque vous convertissez des fonctions INTERSECT
et MINUS
Oracle en MySQL, utilisez des instructions JOIN
ainsi que IN
et EXISTS
comme solution alternative.
Exemples
Fonction Oracle | Mise en œuvre dans Oracle | Compatibilité avec MySQL | Solution MySQL correspondante ou alternative |
---|---|---|---|
UNION |
SELECT COL1 FROM TBL1 UNION SELECT COL1 FROM TBL2 |
Oui | SELECT COL1 FROM TBL1 UNION SELECT COL1 FROM TBL2 |
UNION ALL |
SELECT COL1 FROM TBL1 UNION ALL SELECT COL1 FROM TBL2 |
Oui | SELECT COL1 FROM TBL1 UNION ALL SELECT COL1 FROM TBL2 |
INTERSECT |
SELECT COL1 FROM TBL1 INTERSECT SELECT COL1 FROM TBL2 |
Non | SELECT COL1 FROM TBL1 WHERE COL1 IN (SELECT COL1 FROM TBL2) |
MINUS |
SELECT COL1 FROM TBL1 MINUS SELECT COL1 FROM TBL2 |
Non | SELECT A.COL1 FROM TBL1 A LEFT JOIN TBL2 B ON USING(COL1) WHERE B.COL1 IS NULL |
Fonctions scalaires (à une ligne) et de groupe
MySQL fournit une longue liste de fonctions scalaires (à une ligne) et d'agrégation. Certaines fonctions MySQL sont semblables à leurs équivalents Oracle (même nom et mêmes fonctionnalités, ou avec un nom différent, mais avec des fonctionnalités similaires). En revanche, certaines fonctions MySQL ayant des noms identiques à leurs équivalents Oracle peuvent présenter des fonctionnalités différentes.
Les tableaux suivants indiquent lorsque les fonctions MySQL et Oracle sont équivalentes (même nom et mêmes fonctionnalités, spécifié par "Oui") et lorsqu'une conversion est recommandée (tous les autres cas).
Fonctions de caractères
Fonction Oracle | Spécification ou mise en œuvre de la fonction Oracle | Équivalent MySQL | Fonction MySQL correspondante | Spécification ou mise en œuvre de la fonction MySQL |
---|---|---|---|---|
CONCAT(str1,str2) |
Renvoie str1 concaténé avec str2 :CONCAT('A', 1) = A1 |
Oui | CONCAT |
Équivalent à Oracle :CONCAT('A', 1) = A1 |
LOWER/UPPER |
Renvoie char, avec toutes les lettres minuscules ou majuscules :LOWER('SQL') = sql |
Oui | LOWER/UPPER |
Équivalent à Oracle :LOWER('SQL') = sql |
LPAD/RPAD(expr1,n,expr2) |
Renvoie expr1, complétée à gauche ou à droite (pour atteindre une longueur de n caractères) à l'aide de la séquence de caractères de expr2 :LPAD('A',3,'*') = **A |
Oui | LPAD/RPAD |
Équivalent à Oracle :LPAD('A',3,'*') = **A |
SUBSTR(char,p,n) |
Renvoie une partie de char, commençant à la position de caractère p, avec une longueur de sous-chaîne de n caractères :SUBSTR('MySQL', 3, 3) = SQL |
Oui | SUBSTR(char,p,n) |
Équivalent à Oracle :SUBSTR('MySQL', 3, 3) = SQL |
INSTR(index,str) |
Renvoie la position (index) de la chaîne str :INSTR('MySQL', 'y') = 2 |
Oui | INSTR |
Équivalent à Oracle :INSTR('MySQL', 'y') = 2 |
REPLACE(char,str1,str2) |
Renvoie char avec chaque occurrence d'une chaîne de recherche remplacée par une chaîne de remplacement : REPLACE('ORADB', 'ORA', 'MySQL') |
Oui | REPLACE(char,str1,str2) |
Équivalent à Oracle :REPLACE('ORADB', 'ORA', 'MySQL') |
TRIM(str) |
Coupe les caractères de début ou de fin (ou les deux) d'une chaîne :TRIM(both '-' FROM '-MySQL-') = MySQL |
Oui | TRIM(str) |
Équivalent à Oracle :TRIM(both '-' FROM '-MySQL-') = MySQL |
LTRIM/RTRIM(str) |
Supprime de l'extrémité gauche ou droite de la chaîne tous les caractères qui apparaissent dans la recherche :LTRIM(' MySQL', ' ') = MySQL |
En partie | LTRIM/RTRIM(str) |
Fonction R/LTRIM Oracle, à l'exception du remplacement du paramètre (espace ou chaîne). MySQL R/LTRIM n'élimine que les espaces, en acceptant uniquement la chaîne d'entrée :LTRIM(' MySQL') = MySQL |
ASCII(char) |
Renvoie la représentation décimale (dans le jeu de caractères de la base de données) du premier caractère de char : ASCII('A') = 65 |
Oui | ASCII(char) |
Équivalent à Oracle :ASCII('A') = 65 |
CHR(char) |
Renvoie la valeur du code ASCII (valeur numérique comprise entre 0 et 255) pour un caractère :CHR(65) = A |
En partie avec un nom de fonction différent | CHAR(char) |
MySQL utilise la fonction CHAR pour la même fonctionnalité. Vous devez donc modifier un nom de fonction :CHAR(65) = A |
LENGTH(str) |
Renvoie la longueur d'une chaîne donnée :LENGTH ('MySQL') = 5 |
Oui | LENGTH(str) |
Équivalent à Oracle :LENGTH('MySQL') = 5 |
REGEXP_REPLACE(str1,expr,str2) |
Recherche un modèle d'expression régulière dans une chaîne :REGEXP_REPLACE('John', '[hn].', '1') = Jo1 |
Non | N/A | Compatible uniquement avec la version 8 de MySQL. Pour contourner ce problème, utilisez la fonction REPLACE si possible ou effectuez la conversion vers la couche d'application. |
REGEXP_SUBSTR(str,expr) |
Étend les fonctionnalités de la fonction SUBSTR en recherchant un modèle d'expression régulière dans une chaîne :REGEXP_SUBSTR('https://console.cloud.google.com/sql/instances','https://([[:alnum:]]+\.?){3,4}/?') = https://console.cloud.google.com/ |
Non | N/A | Compatible uniquement avec la version 8 de MySQL. Pour contourner ce problème, utilisez la fonction SUBSTR si possible ou convertissez la fonctionnalité vers la couche d'application. |
REGEXP_COUNT(str,expr) |
Renvoie le nombre d'occurrences d'un modèle dans une chaîne source. | Non | N/A | Vous pouvez aussi convertir la fonctionnalité en couche d'application. |
REGEXP_INSTR(index,expr) |
Recherche un format d'expression régulière dans une position de chaîne (index). | Non | N/A | Compatible uniquement avec la version 8 de MySQL. |
REVERSE(str) |
Renvoie une chaîne inversée REVERSE('MySQL') = LQSyM |
Oui | REVERSE |
Équivalent à Oracle :REVERSE('MySQL') = LQSyM |
Fonctions numériques
Fonction Oracle | Spécification ou mise en œuvre de la fonction Oracle | Équivalent MySQL | Fonction MySQL correspondante | Spécification ou mise en œuvre de la fonction MySQL |
---|---|---|---|---|
ABS(n) |
Valeur absolue de n : ABS(-4.6) = 4.6 |
Oui | ABS |
Équivalent à Oracle :ABS(-4.6) = 4.6 |
CEIL(n) |
Renvoie le plus petit entier supérieur ou égal à n :CEIL(21.4) = 22 |
Oui | CEIL |
Équivalent à Oracle :CEIL(21.4) = 22 |
FLOOR(n) |
Renvoie le plus grand nombre entier égal ou inférieur à n : FLOOR(-23.7) = -24 |
Oui | FLOOR |
Équivalent à Oracle :FLOOR(-23.7) = -24 |
MOD(m,n) |
Renvoie le reste de m divisé par n :MOD(10, 3) = 1 |
Oui | MOD(m,n) |
Équivalent à Oracle :MOD(10,3) = 1 |
ROUND(m,n) |
Renvoie m arrondi à n chiffres à droite de la virgule :ROUND(1.39,1) = 1.4 |
Oui | ROUND |
Équivalent à Oracle :ROUND(1.39,1) = 1.4 |
TRUNC(n1, n2) |
Renvoie n1 tronqué à n2 décimales :TRUNC(99.999) = 99 TRUNC(99.999,0) = 99 |
En partie avec un nom de fonction différent | TRUNCATE(n1, n2) |
La fonction MySQL TRUNCATE doit accepter un nombre en entrée, ainsi qu'un nombre entier pour spécifier la précision à droite de la virgule :TRUNCATE(99.999,0) = 99 |
Fonctions de date et heure
Fonction Oracle | Spécification ou mise en œuvre de la fonction Oracle | Équivalent MySQL | Fonction MySQL correspondante | Spécification ou mise en œuvre de la fonction MySQL |
---|---|---|---|---|
SYSDATE |
Renvoie la date et l'heure actuelles du système d'exploitation sur lequel réside le serveur de base de données :SELECT SYSDATE FROM DUAL = 31-JUL-2019 |
En partie | SYSDATE() |
Le fichier MySQL SYSDATE() doit inclure des parenthèses et renvoie un format de date/heure différent de celui de la fonction SYSDATE Oracle :SELECT SYSDATE() FROM DUAL; = 2019-01-31 10:01:01.0 Notez que la mise en forme de la date et de l'heure peut être modifiée au niveau de la session. |
SYSTIMESTAMP |
Renvoie la date du système, y compris les fractions de seconde et le fuseau horaire :SELECT SYSTIMESTAMP FROM DUAL = 01-JAN-19 07.37.11.622187000 AM +00:00 |
En partie avec un nom de fonction différent | CURRENT_TIMESTAMP |
MySQL renvoie un format de date et d'heure différent de celui d'Oracle. Une mise en forme de la date (ou une fonction de date différente) permettant une correspondance avec le format de date/heure d'origine est requise :SELECT CURRENT_TIMESTAMP FROM DUAL = 2019-01-31 06:55:07 |
LOCAL_TIMESTAMP |
Renvoie la date et l'heure actuelles dans le fuseau horaire de la session dans une valeur dont le type de données est TIMESTAMP :SELECT LOCAL_TIMESTAMP FROM DUAL = 01-JAN-19 10.01.10.123456 PM |
En partie avec une mise en forme de date/heure différente | LOCAL_TIMESTAMP |
MySQL renvoie un format de date et d'heure différent de celui d'Oracle. Une mise en forme de la date/heure (ou une fonction de date différente) permettant une correspondance avec le format de date/heure d'origine est requise :SELECT LOCAL_TIMESTAMP FROM DUAL = 2019-01-01 10:01:01.0 |
CURRENT_DATE |
Renvoie la date actuelle dans le fuseau horaire de la session :SELECT CURRENT_DATE FROM DUAL = 31-JAN-19 |
En partie avec une mise en forme de date/heure différente | CURRENT_DATE |
MySQL renvoie un format de date et d'heure différent de celui d'Oracle. Une mise en forme de la date/heure (ou une fonction de date différente) permettant une correspondance avec le format de date/heure d'origine est requise :SELECT CURRENT_DATE FROM DUAL = 2019-01-31 |
CURRENT_TIMESTAMP |
Renvoie la date et l'heure actuelles dans le fuseau horaire de la session :SELECT CURRENT_TIMESTAMP FROM DUAL = 31-JAN-19 06.54.35.543146 AM +00:00 |
En partie avec une mise en forme de date/heure différente | CURRENT_TIMESTAMP |
MySQL renvoie un format de date et d'heure différent de celui d'Oracle. Une mise en forme de la date/heure (ou une fonction de date différente) permettant une correspondance avec le format de date/heure d'origine est requise :SELECT CURRENT_TIMESTAMP FROM DUAL = 2019-01-31 06:55:07 |
ADD_MONTHS |
Renvoie la date plus les mois entiers :ADD_MONTHS(SYSDATE, 1) = 31-JAN-19 |
En partie avec un nom de fonction différent | ADDDATE |
Pour obtenir les mêmes fonctionnalités, MySQL utilise la fonction ADDDATE :ADDDATE(SYSDATE(), 1) = 2019-08-01 06:42:49.0 Par défaut, MySQL renvoie une date, une heure, une plage et un format différents de ceux d'Oracle. Une mise en forme de la date/heure (ou une fonction de date différente) permettant une correspondance avec le format de date/heure d'origine est requise. |
EXTRACT (partie de la date) |
Renvoie la valeur d'un champ de date/heure spécifié à partir d'une expression de date/heure ou d'intervalle :EXTRACT(YEAR FROM DATE '2019-01-31') = 2019 |
Oui | EXTRACT (partie de la date) |
Équivalent à Oracle :EXTRACT(YEAR FROM DATE '2019-01-31') = 2019 |
LAST_DAY |
Renvoie la date du dernier jour du mois :LAST_DAY('01-JAN-2019') = 31-JAN-19 |
En partie avec une mise en forme de date/heure différente | LAST_DAY |
MySQL renvoie un format de date et d'heure différent de celui d'Oracle. Une mise en forme de la date/heure (ou une fonction de date différente) permettant une correspondance avec le format de date/heure d'origine est requise :LAST_DAY('2019-01-01') = 2019-01-31 |
MONTH_BETWEEN |
Renvoie le nombre de mois compris entre les dates date1 et date2 :MONTHS_BETWEEN( SYSDATE, SYSDATE-60) = 1.96 |
En partie avec un nom de fonction différent | PERIOD_DIFF(date1,date2) |
La fonction MySQL PERIOD_DIFF renvoie la différence en mois entre deux "périodes" (au format YYMM ou YYYYMM ) sous forme de nombre entier :PERIOD_DIFF( '201903', '201901') = 2 Pour obtenir les mêmes valeurs qu'avec la fonction Oracle MONTH_BETWEEN , une conversion plus spécifique est requise. |
TO_CHAR (date/heure) |
Convertit un type de données de date/heure ou d'horodatage en une valeur de type de données VARCHAR2 au format spécifié par le format de date :TO_CHAR( SYSDATE,'DD-MM-YYYY HH24:MI:SS') = 01-01-2019 10:01:01 |
En partie avec un nom de fonction différent | DATE_FORMAT |
La fonction MySQL DATE_FORMAT met en forme une date comme spécifié dans une définition de format de date :DATE_FORMAT( SYSDATE(),'%d-%m-%Y %H:%i:%s') = 01-01-2019 10:01:01 |
Fonctions d'encodage et de décodage
Fonction Oracle | Spécification ou mise en œuvre de la fonction Oracle | Équivalent MySQL | Fonction MySQL correspondante | Spécification ou mise en œuvre de la fonction MySQL |
---|---|---|---|---|
DECODE |
Compare l'expression à chaque valeur de recherche (une par une) à l'aide de la fonctionnalité d'une instruction IF-THEN-ELSE . |
Non | CASE |
Utilisez l'instruction MySQL CASE pour obtenir des fonctionnalités similaires. |
DUMP |
Renvoie une valeur VARCHAR2 contenant le code du type de données, la longueur en octets et la représentation interne d'une expression donnée. |
Non | N/A | Non compatible |
ORA_HASH |
Calcule une valeur de hachage pour une expression donnée. | Non | MD5/SHA |
Utilisez MySQL MD5 pour la somme de contrôle de 128 bits ou la fonction SHA pour la somme de contrôle de 160 bits afin de générer des valeurs de hachage. |
Fonctions de conversion
Fonction Oracle | Spécification ou mise en œuvre de la fonction Oracle | Équivalent MySQL | Fonction MySQL correspondante | Spécification ou mise en œuvre de la fonction MySQL |
---|---|---|---|---|
CAST |
Convertit un type de données intégré ou une valeur de type collection en un autre type de données intégré ou une autre valeur de type collection : CAST('1' as int) + 1 = 2 |
En partie | CAST |
La fonction MySQL CAST est semblable à la fonctionnalité Oracle, mais dans certains cas, elle doit être ajustée selon qu'une conversion explicite ou implicite est requise :CAST('1' AS SIGNED) + 1 = 2 |
CONVERT |
Convertit une chaîne de caractères d'un jeu de caractères en une autre : CONVERT('Ä Ê Í Õ Ø A B C D E ', 'US7ASCII', 'WE8ISO8859P1') = ?? ?? ?? A B C |
En partie | CONVERT |
La fonction MySQL CONVERT nécessite quelques ajustements de la syntaxe et des paramètres pour renvoyer les résultats exacts de la même façon que la fonction Oracle :CONVERT('Ä Ê Í A B C ' USING utf8) = Ä Ê Í A B C |
TO_CHAR (chaîne/numérique) |
La fonction convertit un nombre ou une date en chaîne : TO_CHAR(22.73,'$99.9') = $22.7 |
Non | FORMAT |
La fonction MySQL FORMAT applique le formatage "#,###.##" à un nombre, en arrondissant la valeur à un certain nombre de décimales, puis elle renvoie le résultat sous forme de chaîne. Elle possède des fonctionnalités différentes de celles d'Oracle :CONCAT('$', FORMAT(22.73, 1)) = $22.7 |
TO_DATE |
La fonction Oracle TO_DATE convertit une chaîne en date en utilisant le format de date/heure spécifique à la source :TO_DATE( '2019/01/01', 'yyyy-mm-dd') = 01-JAN-2019 |
En partie avec un nom de fonction et une mise en forme de date/heure différents | STR_TO_DATE |
La fonction MySQL STR_TO_DATE utilise une chaîne et renvoie une date au format (date/heure) spécifié :STR_TO_DATE( '2019/01/01', '%Y/%m/%d') = 2019-01-01 |
TO_NUMBER |
Convertit l'expression en une valeur dont le type de données est NUMBER :TO_NUMBER('01234') = 1234 |
Non | CAST |
Vous pouvez également utiliser la fonction MySQL CAST pour renvoyer le même résultat qu'avec Oracle TO_NUMBER :CAST('01234' as SIGNED) = 1234 |
Fonctions SELECT conditionnelles
Fonction Oracle | Spécification ou mise en œuvre de la fonction Oracle | Équivalent MySQL | Fonction MySQL correspondante | Spécification ou mise en œuvre de la fonction MySQL |
---|---|---|---|---|
CASE |
L'instruction CASE effectue un choix dans une séquence de conditions et exécute une instruction correspondante avec la syntaxe suivante :CASE WHEN condition THEN result [WHEN ...] [ELSE result] END |
Oui | CASE |
En plus de la fonction CASE , MySQL est également compatible avec l'utilisation de la gestion conditionnelle IF/ELSE dans l'instruction SELECT :CASE WHEN condition THEN result [WHEN ...] [ELSE result] END |
Fonctions nulles
Fonction Oracle | Spécification ou mise en œuvre de la fonction Oracle | Équivalent MySQL | Fonction MySQL correspondante | Spécification ou mise en œuvre de la fonction MySQL |
---|---|---|---|---|
COALESCE |
Renvoie la première expression non nulle de la liste d'expressions : COALESCE( null, '1', 'a') = a |
Oui | COALESCE |
Équivalent à Oracle :COALESCE( null, '1', 'a') = 1 |
NULLIF |
Compare les expressions expr1 et expr2m. Si elles sont égales, la fonction renvoie la valeur "null". Si elles ne sont pas égales, la fonction renvoie "expr1" : . NULLIF('1', '2') = a |
Oui | NULLIF |
Équivalent à Oracle :NULLIF('1', '2') = a |
NVL |
Remplace la valeur "null" (renvoyée sous forme de valeur vide) par une chaîne dans les résultats d'une requête : NVL(null, 'a') = a |
Non | IFNULL |
La fonction MySQL équivalente serait la fonction IFNULL , qui remplace les valeurs "null" par une chaîne donnée :IFNULL(null, 'a') = a |
NVL2 |
Détermine la valeur renvoyée par une requête selon qu'une expression spécifiée est nulle ou non nulle. |
Non | CASE |
L'instruction CASE effectue un choix dans une séquence de conditions et exécute une instruction correspondante : CASE WHEN condition THEN result [WHEN ...] [ELSE result] END |
Fonctions d'environnement et d'identification
Fonction Oracle | Spécification ou mise en œuvre de la fonction Oracle | Équivalent MySQL | Fonction MySQL correspondante | Spécification ou mise en œuvre de la fonction MySQL |
---|---|---|---|---|
SYS_GUID |
Génère et renvoie un identifiant global unique (valeur RAW) composé de 16 octets :SELECT SYS_GUID() FROM DUAL = 8EFA4A31468B4C6DE05011AC0200009E |
Non | REPLACE et UUID |
Pour contourner ce problème, utilisez les fonctions MySQL REPLACE et UUID pour simuler la fonction Oracle SYS_GUID :REPLACE( UUID(), '-', '') |
UID |
Renvoie un entier qui identifie de manière unique l'utilisateur de la session (l'utilisateur qui s'est connecté) : SELECT UID FROM DUAL = 43 |
Non | N/A | N/A |
USER |
Renvoie le nom de l'utilisateur de la session actuelle :SELECT USER FROM DUAL = UserName |
En partie | USER + INSTR + SUBSTR |
La fonction USER de MySQL renvoie le nom de l'utilisateur et celui du serveur auquel il est connecté (root@IP ). Pour ne récupérer que le nom d'utilisateur, utilisez des fonctions supplémentaires :SELECT SUBSTR(USER(), 1, INSTR(USER(), '@') -1) FROM DUAL = root |
USERENV |
Renvoie des informations sur la session utilisateur actuelle avec la configuration de paramètre actuelle :SELECT USERENV('LANGUAGE') FROM DUAL = ENGLISH_AMERICA.AL32UTF8 |
Non | SHOW SESSION VARIABLES |
Utilisez l'instruction MySQL SHOW SESSION VARIABLES pour afficher les paramètres de la session actuelle :SHOW SESSION VARIABLES LIKE '%collation%'; = utf8_general_ci |
ROWID |
Le serveur Oracle attribue à chaque ligne de chaque table un ROWID unique pour identifier la ligne dans la table. ROWID est l'adresse de la ligne contenant le numéro de l'objet de données, le bloc de données de la ligne, la position de la ligne et le fichier de données. |
Non | N/A | Si possible, essayez d'émuler la même fonctionnalité avec d'autres fonctions MySQL. |
ROWNUM |
Renvoie un nombre représentant l'ordre dans lequel une ligne est sélectionnée par Oracle dans une table ou des tables jointes. | Non | N/A | Si possible, essayez d'émuler la même fonctionnalité avec d'autres fonctions ou variables de session MySQL. |
Fonctions d'agrégation (groupe)
Fonction Oracle | Spécification de la fonction Oracle ou mise en œuvre |
Équivalent MySQL |
Fonction MySQL correspondante | Spécification ou mise en œuvre de la fonction MySQL |
---|---|---|---|---|
AVG |
Renvoie la valeur moyenne de la colonne ou de l'expression. | Oui | AVG |
Équivalent à Oracle |
COUNT |
Renvoie le nombre de lignes renvoyées par une requête. | Oui | COUNT |
Équivalent à Oracle |
COUNT (DISTINCT) |
Renvoie le nombre de valeurs uniques dans la colonne ou l'expression. | Oui | COUNT (DISTINCT) |
Équivalent à Oracle |
MAX |
Renvoie la valeur maximale de la colonne ou de l'expression. | Oui | MAX |
Équivalent à Oracle |
MIN |
Renvoie la valeur minimale de la colonne ou de l'expression. | Oui | MIN |
Équivalent à Oracle |
SUM |
Renvoie la somme des valeurs de la colonne ou de l'expression. | Oui | SUM |
Équivalent à Oracle |
LISTAGG |
Affiche les données de chaque groupe sur une seule ligne spécifiée dans la clause ORDER BY en concaténant les valeurs de la colonne de mesure :SELECT LISTAGG( DEPARTMENT_NAME, ', ') WITHIN GROUP (ORDER BY DEPARTMENT_NAME) DEPT FROM DEPARTMENTS; |
Non | GROUP_CONCAT |
Utilisez la fonction MySQL GROUP_CONCAT pour renvoyer des résultats semblables à ceux d'Oracle, des différences de syntaxe étant à prévoir dans certains cas :SELECT GROUP_CONCAT( DEPARTMENT_NAME ORDER BY DEPARTMENT_NAME SEPARATOR ', ') DEPT FROM DEPARTMENTS; |
Oracle 12c Fetch
Fonction Oracle | Spécification de la fonction Oracle ou mise en œuvre |
Équivalent MySQL |
Fonction MySQL correspondante | Spécification ou mise en œuvre de la fonction MySQL |
---|---|---|---|---|
FETCH |
Récupère les lignes de données de l'ensemble de résultats d'une requête sur plusieurs lignes : SELECT * FROM EMPLOYEES FETCH FIRST 10 ROWS ONLY; |
Non | LIMIT | Utilisez la clause MySQL LIMIT pour ne récupérer qu'un ensemble spécifique d'enregistrements :SELECT * FROM EMPLOYEES LIMIT 10; |
Filtrage de base, opérateurs et sous-requêtes
Lors de la conversion, le filtrage de base, les fonctions d'opérateur et les sous-requêtes sont relativement simples à effectuer et ne nécessitent presque aucun effort.
Notes de conversion
Vous devez examiner et adapter les formats de date, car les formats Oracle et MySQL renvoient des résultats par défaut différents :
- La fonction
SYSDATE
Oracle renvoie par défaut01-AUG-19
. - La fonction
SYSDATE()
MySQL renvoie par défaut2019-08-01 12:04:05
. - Les formats de date et d'heure peuvent être définis à l'aide des fonctions 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)
.
Fonction ou sous-requête Oracle | Équivalent MySQL | Fonction ou sous-requête MySQL correspondante | Spécification ou mise en œuvre de la fonction MySQL |
---|---|---|---|
EXISTS/NOT EXISTS |
Oui | EXISTS/NOT EXISTS |
SELECT * FROM DEPARTMENTS D WHERE EXISTS (SELECT 1 FROM EMPLOYEES E WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID); |
IN/NOT IN |
Oui | IN/NOT IN |
SELECT * FROM DEPARTMENTS D WHERE DEPARTMENT_ID IN (SELECT DEPARTMENT_ID FROM EMPLOYEES E); |
LIKE/NOT LIKE |
Oui | LIKE/NOT LIKE |
SELECT * FROM EMPLOYEES WHERE FIRST_NAME LIKE '_e_n%'; |
BETWEEN/NOT BETWEEN |
Oui | BETWEEN/NOT BETWEEN |
SELECT * FROM EMPLOYEES WHERE EXTRACT(YEAR FROM HIRE_DATE) NOT BETWEEN 2001 and 2004; |
AND/OR |
Oui | AND/OR |
SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID IN(100, 101) AND (SALARY >= 1000 OR HIRE_DATE <= '2006-02-05'); |
SubQuery |
Oui | SubQuery |
MySQL accepte les sous-requêtes au niveau SELECT , pour les instructions JOIN et pour le filtrage dans les clauses 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; |
Opérateurs | Oui | Opérateurs | MySQL est compatible avec tous les opérateurs de base :> | >= | < | <= | = | <> | != |
Fonctions d'analyse (ou fonctions de fenêtre et de classement)
Les fonctions d'analyse Oracle étendent la fonctionnalité des fonctions d'analyse SQL standards en fournissant des capacités de calcul des valeurs agrégées en fonction d'un groupe de lignes. Ces fonctions peuvent être appliquées à des ensembles de résultats partitionnés de manière logique dans une seule expression de requête. Elles sont généralement utilisées conjointement avec des rapports et des analyses d'informatique décisionnelle et permettent d'améliorer les performances des requêtes. Il n'est donc pas nécessaire d'utiliser un code SQL plus complexe et non analytique pour parvenir à un tel résultat.
Notes de conversion
- La version 5.7 de MySQL ne fournit pas de fonctions d'analyse permettant de convertir des instructions SQL simples. Cependant, cette fonctionnalité a été partiellement ajoutée dans la version 8 de MySQL. Il est donc nécessaire de prévoir un effort manuel dédié à la conversion des fonctions analytiques dans le cadre du processus de migration.
- Vous pouvez également réécrire le code afin de supprimer l'utilisation de fonctions d'analyse et ainsi revenir à des solutions de code SQL plus traditionnelles, ou encore déplacer cette logique vers une couche d'application.
Le tableau suivant répertorie les fonctions d'analyse courantes d'Oracle.
Famille de fonctions | Fonctions associées | Compatible avec MySQL 5.7 |
---|---|---|
Analyse et classement | RANK AVERAGE_RANK DENSE_RANK RANK ROW_NUMBER PERCENT_RANK CUME_DIST NTILE FIRST_VALUE LAST_VALUE OVER (PARTITION BY...) |
Non |
Hiérarchique | CONNECT BY HIER_ANCESTOR HIER_CHILD_COUNT HIER_DEPTH HIER_LEVEL HIER_ORDER HIER_PARENT HIER_TOP |
Non |
Lag | LAG LAG_VARIANCE LAG_VARIANCE_PERCENT LEAD LEAD_VARIANCE LEAD_VARIANCE_PERCENT |
Non |
Expression de table commune (CTE)
Les CTE permettent de mettre en œuvre la logique du code séquentiel afin de réutiliser du code SQL pouvant être trop complexe ou peu efficace pour une utilisation polyvalente. Les CTE peuvent être nommées, puis utilisées plusieurs fois dans différentes parties d'une instruction SQL à l'aide de la clause WITH
.
Notes de conversion
- MySQL version 5.7 n'est pas compatible avec les CTE, contrairement à MySQL version 8.
- En guise de solution alternative, vous pouvez utiliser des tables dérivées ou des sous-requêtes, ou encore réécrire l'instruction SQL pour éliminer la fonctionnalité CTE.
Exemples
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; |
Instruction MERGE
L'instruction MERGE
(ou UPSERT
) permet de spécifier des instructions SQL uniques permettant d'effectuer des opérations LMD de manière conditionnelle dans une opération MERGE
, au lieu d'une seule opération LMD exécutée séparément. Elle sélectionne les enregistrements de la table source, puis, en spécifiant une structure logique, effectue automatiquement plusieurs opérations LMD sur la table cible. Cette fonctionnalité vous permet d'éviter l'utilisation de plusieurs insertions, mises à jour ou suppressions. Notez que MERGE
est une instruction déterministe, ce qui signifie qu'une fois qu'une ligne a été traitée par l'instruction MERGE
, elle ne peut plus être traitée à l'aide de la même instruction MERGE
.
Notes de conversion
MySQL 5.7 n'est pas compatible avec la fonctionnalité MERGE
, contrairement à Oracle. Pour simuler partiellement la fonctionnalité MERGE
, MySQL fournit les instructions REPLACE
et INSERT… ON DUPLICATE KEY UPDATE
:
REPLACE
: fonctionne de la même manière qu'une instructionINSERT
, à l'exception que, si une ancienne ligne de la table a la même valeur qu'une nouvelle ligne pour un indexPRIMARY KEY
ouUNIQUE
, l'ancienne ligne est supprimée avant l'insertion de la nouvelle ligne.INSERT… ON DUPLICATE KEY UPDATE
: si une ligne insérée entraîne la présence d'une valeur en double dans un indexPRIMARY KEY
ouUNIQUE
, unUPDATE
de l'ancienne ligne est utilisé afin d'éliminer l'exception de clé en double, comme dans l'exemple suivant :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;
Une autre solution consiste à convertir la fonctionnalité MERGE
en procédure stockée pour gérer les opérations LMD à l'aide des commandes INSERT
, UPDATE
et DELETE
avec gestion des exceptions et des doublons.
Suggestions pour les instructions SQL
Oracle fournit un large éventail de suggestions de requête SQL qui permettent aux utilisateurs d'influencer le comportement de l'optimiseur et sa prise de décision, afin de produire des plans d'exécution de requête plus efficaces. Oracle accepte plus de 60 suggestions différentes de bases de données. MySQL fournit un ensemble limité de suggestions de requête.
En général, la version MySQL 5.7 accepte deux types de suggestions de requête : OPTIMIZER
HINTS
et INDEX HINTS
.
Les suggestions d'optimiseur MySQL permettent de contrôler le comportement de l'optimiseur dans des instructions SQL individuelles, par exemple :
SELECT /*+ NO_RANGE_OPTIMIZATION(tbl PRIMARY, col1_idx) */ col1 FROM tbl;
MySQL dans la version 5.7 de MySQL
Nom de la suggestion | Présentation de la suggestion | Champs d'application |
---|---|---|
BKA, NO_BKA |
Affecte le traitement par jointure des accès de clés par lots | Bloc de requête, table |
BNL, NO_BNL |
Affecte le traitement des jointures par boucle imbriquée | Bloc de requête, table |
MAX_EXECUTION_TIME |
Limite le temps d'exécution de l'instruction | Global |
MRR, NO_MRR |
Affecte l'optimisation de la lecture sur plusieurs plages | Table, index |
NO_ICP |
Affecte l'optimisation pushdown des conditions d'index | Table, index |
NO_RANGE_OPTIMIZATION |
Affecte l'optimisation de la plage | Table, index |
QB_NAME |
Attribue un nom au bloc de requêtes | Bloc de requête |
SEMIJOIN, NO_SEMIJOIN |
Affecte les stratégies de semi-jointure | Bloc de requête |
SUBQUERY |
Affecte la matérialisation des stratégies de sous-requêtes IN à EXISTS . |
Bloc de requête |
Les suggestions d'index MySQL fournissent à l'optimiseur des informations sur le choix des index lors du traitement des requêtes. Les mots clés USE
, FORCE
ou IGNORE
permettent de contrôler le processus d'utilisation des index de l'optimiseur, par exemple :
SELECT * FROM tbl USE INDEX (col1_index, col2_index);
-- OR
SELECT * FROM tbl IGNORE INDEX (col1_index, col2_index);
Notes de conversion
Comme il existe des différences majeures entre Oracle et l'optimiseur MySQL, et que la correspondance est très limitée, voire inexistante, entre les suggestions de requête Oracle et MySQL, nous vous recommandons de convertir toutes les instructions Oracle SQL contenant des suggestions de requête non spécifiées sur la base de données MySQL cible.
Effectuez un réglage des performances MySQL en vous servant des outils MySQL (par exemple, MySQL Workbench pour les tableaux de bord en temps réel), ainsi que des fonctionnalités telles que l'examen des requêtes à l'aide de plans d'exécution et l'ajustement des paramètres d'instance ou de session en fonction du cas d'utilisation.
Plans d'exécution
L'objectif principal des plans d'exécution est de fournir un aperçu des choix effectués par l'optimiseur de requête pour accéder aux données de la base de données. L'optimiseur de requête génère des plans d'exécution pour les instructions SELECT
, INSERT
, UPDATE
et DELETE
pour les utilisateurs de base de données, ce qui offre aux administrateurs une visibilité accrue sur des requêtes et des opérations LMD spécifiques. Ces informations sont particulièrement utiles lorsque vous devez ajuster les performances des requêtes, par exemple pour évaluer les performances des index ou pour déterminer si des index manquants doivent être créés.
Les plans d'exécution peuvent être affectés par les volumes de données, les statistiques de données et les paramètres d'instance (paramètres globaux ou de session).
Remarques sur les conversions
Les plans d'exécution ne sont pas des objets de base de données qui doivent être migrés. Il s'agit plutôt d'une boîte à outils permettant d'analyser les différences de performances entre Oracle et MySQL lorsque ceux-ci exécutent les mêmes instructions sur des ensembles de données identiques.
La syntaxe, les fonctionnalités et les résultats fournis par les plans d'exécution diffèrent entre MySQL et Oracle.
Exemples
Plan d'exécution Oracle |
---|
SQL> EXPLAIN PLAN FOR SELECT * FROM EMPLOYEES WHERE EMPLOYEE_ID = 105; |
Plan d'exécution MySQL |
mysql> EXPLAIN SELECT * FROM EMPLOYEES WHERE EMPLOYEE_ID = 105; |
Procédures stockées, fonctions et déclencheurs
PL/SQL est le langage procédural étendu Oracle utilisé pour créer, stocker et appliquer des solutions basées sur du code dans la base de données. En général, les procédures et les fonctions stockées dans la base de données sont des éléments de code constitués sur la base d'un langage procédural étendu ANSI SQL et SQL (par exemple, PL/SQL pour Oracle, PL/pgSQL pour PostgreSQL et MySQL pour MySQL). MySQL utilise le même nom que la base de données pour son propre langage procédural étendu.
Le but de ces procédures et fonctions stockées est de fournir des solutions pour des exigences plus adaptées à l'exécution depuis la base de données et non depuis l'application (par exemple, performances, compatibilité et sécurité). Bien que les procédures stockées et les fonctions utilisent toutes deux PL/SQL, les procédures stockées sont principalement utilisées pour effectuer des opérations LDD/LMD, alors que les fonctions sont principalement utilisées pour effectuer des calculs afin de renvoyer des résultats spécifiques.
Langage procédural PL/SQL vers MySQL
Du point de vue de la migration du code PL/SQL à MySQL, l'implémentation procédurale de MySQL est différente de celle d'Oracle. Par conséquent, la migration du code est nécessaire pour convertir les fonctionnalités PL/SQL d'Oracle en procédures et fonctions stockées MySQL. En outre, Oracle Package et Package Body ne sont pas acceptés par MySQL. Par conséquent, lorsque vous effectuez une conversion de code, convertissez ces éléments (ou analysez-les) en unités de code MySQL uniques. Notez que les procédures et fonctions MySQL stockées sont également appelées routines.
Propriétaire de l'objet de code
Dans Oracle, le propriétaire d'une procédure ou d'une fonction stockée est un utilisateur spécifique. Dans MySQL, le propriétaire est un schéma spécifique (créé dans une base de données par un utilisateur de base de données).
Droits et sécurité des objets de code
Dans Oracle, pour créer une procédure ou une fonction stockée, l'utilisateur doit disposer du droit système CREATE PROCEDURE
(pour créer des procédures ou des fonctions pour des utilisateurs différents, les utilisateurs de la base de données doivent disposer du droit CREATE
ANY PROCEDURE
). Pour exécuter une procédure ou une fonction stockée, les utilisateurs de la base de données doivent disposer du droit EXECUTE
.
Dans MySQL, pour créer un élément de code, l'utilisateur doit disposer du droit CREATE
ROUTINE
et du droit EXECUTE
. La clause MySQL DEFINER
définit l'utilisateur créateur pour l'objet de code, et l'utilisateur doit disposer des droits appropriés tels que CREATE ROUTINE
.
Syntaxe des procédures et fonctions stockées MySQL
L'exemple suivant montre la syntaxe de procédure et de fonction stockées 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