• Aucun résultat trouvé

Différences entre MySQL et le standard SQL-92

Chapitre 1. Informations générales

1.5. Quels standards respecte MySQL ?

1.5.5. Différences entre MySQL et le standard SQL-92

Nous tâchons de rendre le serveur MySQL compatible avec le standard ANSI SQL, et le standard ODBC SQL, mais dans certains cas, MySQL se comporte différemment.

• Pour les colonnes de typeVARCHAR, les espaces terminaux sont supprimés lors du stockage de la valeur. SeeSection 1.5.7,

« Erreurs connues, et limitations de MySQL ».

• Dans certains cas, les colonnesCHARsont transformées automatiquement en colonnesVARCHAR. SeeSection 13.2.5.1,

« Modification automatique du type de colonnes ».

• Les droits d'un utilisateur sur une table ne sont pas supprimés si la table est détruite. Vous devez explicitement utiliser la commande REVOKEpour supprimer les droits d'un utilisateur sur une table. SeeSection 13.5.1.3, « Syntaxe deGRANTetREVOKE».

1.5.5.1. Sous-requêtes

MySQL 4.1 supporte les sous-requêtes et les tables dérivées (vues anonymes). Une ``sous-requête'' est une commandeSELECT imbriquée dans une autre commande. Une ``table dérivée'' (vues anonymes) est une sous-requête placée dans une clauseFROMd'une autre commande. SeeSection 13.1.8, « Sous-sélections (SubSELECT) ».

Pour les versions de MySQL antérieure à la 4.1, la plupart des sous-requêtes peuvent être réécrites avec des jointures et d'autres méthodes. VoyezSection 13.1.8.11, « Se passer des sous-requêtes avec les premières versions de MySQL »pour des exemples d'illustration.

1.5.5.2. SELECT INTO TABLE

Le serveur MySQL ne supporte pas encore l'extension Oracle SQL :SELECT ... INTO TABLE .... A la place, le serveur MySQL supporte la syntaxe ANSI SQLINSERT INTO ... SELECT ..., qui revient au même. SeeSection 13.1.4.1, « Syntaxe deINSERT ... SELECT».

INSERT INTO tblTemp2 (fldID) SELECT tblTemp1.fldOrder_ID

FROM tblTemp1 WHERE tblTemp1.fldOrder_ID > 100;

Alternativement, vous pouvez utiliserSELECT INTO OUTFILE...etCREATE TABLE ... SELECT.

Depuis la version 5.0, MySQL supporteSELECT ... INTOavec les variables serveur. La même syntaxe peut aussi être utilisée dans les procédures stockées, en utilisant les curseurs et les variables locales. SeeSection 19.2.9.3, « Syntaxe deSELECT ... INTO».

Informations générales

1.5.5.3. Transactions et opérations atomiques

Le serveur MySQL (version 3.23MySQL-maxet toutes les versions 4.0 et plus récent) supporte les transactions avec les gestionnaires de tablesInnoDBetBDB.InnoDBdispose aussi de la compatibilitéACIDtotale. SeeChapitre 14, Moteurs de tables MySQL et types de table.

Toutefois, les tables non transactionnelles de MySQL telles queMyISAMexploitent un autre concept pour assurer l'intégrité des données, appelé ``opérations atomiques''. Les opérations atomiques disposent d'une bien meilleure protection des données pour des performances également accrues. Comme MySQL supporte les deux méthodes, l'utilisateur est capable de choisir celle qui correspond à ses besoins, suivant qu'il a besoin de vitesse ou de sécurité. Ce choix peut être fait table par table.

Comment exploiter les capacités de MySQL pour protéger l'intégrité des données, et comment ces fonctionnalités se comparent elles avec les méthodes transactionnelles ?

1. En mode transactionnel, si votre application a été écrite en dépendant de l'appel deROLLBACKau lieu deCOMMITdans les situations critiques, les transactions sont plus pratiques. Les transactions s'assurent que les modifications non achevées ou les activités corrosives ne sont pas archivées dans la base. Le serveur a l'opportunité d'annuler automatiquement l'opération, et votre base de données est sauve.

Le serveur MySQL, dans la plupart des cas, vous permet de résoudre les problèmes potentiels en incluant de simples vérifications avant les modifications, et en exécutant des scripts simples pour vérifier l'intégrité de vos bases de données, ainsi que les incohérences, et pour réparer automatiquement les problèmes, ou encore vous alerter si une erreur est identifiée. Notez qu'en utilisant simplement le log de MySQL, ou en utilisant un log supplémentaire, vous pouvez normalement réparer à la perfection toutes les tables, sans aucune perte de données.

2. Souvent, les modifications de données transactionnelles fatales peuvent être réécrites de manière atomique. En général, tous les problèmes d'intégrité que les transactions résolvent peuvent être corrigés avec la commandeLOCK TABLESou des modifications atomiques, qui assurent que vous n'aurez jamais d'annulation automatique de la base, ce qui est un problème commun des bases transactionnelles.

3. Même un système transactionnel peut perdre des données si le serveur s'arrête. La différence entre les systèmes repose alors dans ce petit laps de temps où ils peuvent perdre des données. Aucun système n'est sécurisé à 100%, mais simplement ``suffisamment sécurisé''. Même Oracle, réputé pour être la plus sûre des bases de données transactionnelles, est montré du doigt pour perdre des données dans ces situations.

Pour être tranquille avec MySQL, que vous utilisiez les tables transactionnelles ou pas, vous n'avez besoin que de sauvegardes et de logs de modifications. Avec ces deux outils, vous pourrez vous protéger de toutes les situations que vous pourriez rencontrer avec d'autres bases de données transactionnelles. De toute manière, il est bon d'avoir des sauvegardes, indépendamment de la base que vous utilisez.

La méthode transactionnelle a ses avantages et ses inconvénients. De nombreux utilisateurs et développeurs d'applications dépendent de la facilité de pallier un problème lorsqu'une annulation semble nécessaire ou presque. Cependant, même si vous êtes néophyte des opérations atomiques, ou plus familier avec les transactions, prenez en considération le gain de vitesse que les tables non

transactionnelles offrent. Ces gains vont de 3 a 5 fois la vitesse des tables transactionnelles les plus rapides et les mieux optimisées.

Dans des situations où l'intégrité est de la plus grande importance, le serveur MySQL assure une intégrité du niveau des transactions, ou encore mieux avec les tables non transactionnelles. Si vous verrouillez les tables avecLOCK TABLES, toutes les modifications seront bloquées jusqu'à ce que la vérification d'intégrité soit faite (à comparer avec un verrou en écriture), les lectures et insertions sont toujours possibles. Les nouvelles lignes ne seront pas accessibles en lecture tant que le verrou n'aura pas été levé. AvecINSERT DELAYED, vous pouvez faire attendre les insertions dans une pile, jusqu'à ce que les verrous soit levés, sans que le client n'attende cette levée de verrou. SeeSection 13.1.4.2, « Syntaxe deINSERT DELAYED».

``Atomique'', avec le sens que nous lui donnons, n'a rien de magique. Ce terme signifie simplement que vous pouvez être certain que lorsque vous modifiez des données dans une table, aucun autre utilisateur ne peut interférer avec votre opération, et qu'il n'y aura pas d'annulation automatique (ce qui pourrait arriver avec des tables transactionnelles si nous ne sommes pas trop soigneux). Le serveur MySQL garantit aussi qu'il n'y aura pas de lectures erronées.

Voici quelques techniques pour travailler avec des tables non transactionnelles :

• Les boucles qui requièrent les transactions peuvent normalement être implémentées avec la commandeLOCK TABLES, et vous n'avez nul besoin de curseur lorsque vous modifiez des lignes à la volée.

• Pour éviter d'utiliser l'annulationROLLBACK, vous pouvez adopter la stratégie suivante :

1. Utilisez la commandeLOCK TABLES ...pour verrouiller toutes les tables que vous voulez utiliser.

2. Testez vos conditions.

3. Modifiez si tout est correct.

4. UtilisezUNLOCK TABLESpour libérer vos tables.

Ceci est probablement une méthode bien plus rapide que ne le proposent les transactions, avec des annulationsROLLBACKpossibles mais pas certaines. La seule situation que ce cas ne prend pas en compte est l'interruption du processus au milieu d'une mise à jour.

Dans ce cas, tous les verrous seront levés, mais certaines modifications peuvent ne pas avoir été exécutées.

• Vous pouvez aussi utiliser des fonctions pour modifier des lignes en une seule opération. Vous pouvez créer une application très efficace en utilisant cette technique :

• Modifiez les champs par rapport à leur valeur actuelle.

• Modifiez uniquement les champs que vous avez réellement changé.

Par exemple, lorsque nous modifions les données d'un client, nous ne modifions que les données du client qui ont changé et nous vérifions uniquement si les données modifiées ou les données qui en dépendent ont changé comparativement aux données originales. Les tests sur les données modifiées sont faits avec la clauseWHEREdans la commandeUPDATE. Si la ligne a été modifiée, nous indiquons au client :"Some of the data you have changed has been changed by another user". En fran¸ais : "certaines données que vous voulez modifier ont été modifiées par un autre utilisateur". Puis nous affichons l'ancienne ligne et la nouvelle ligne, pour laisser l'utilisateur décider quelle version il veut utiliser.

Cela nous conduit à un résultat proche du verrouillage de ligne, mais en fait, c'est bien mieux, car nous ne modifions que les colonnes qui en ont besoin, en utilisant des valeurs relatives. Cela signifie qu'une commandeUPDATEtypique ressemble à ceci :

UPDATE tablename SET pay_back=pay_back+'relative change';

UPDATE customer SET

customer_date='current_date', address='new address', phone='new phone', dette=dette+'emprunt' WHERE

customer_id=id AND address='old address' AND phone='old phone';

Comme vous pouvez le voir, c'est très efficace, et fonctionne même si un autre client a modifié la valeurpay_backoudette.

• Dans de nombreuses situations, les utilisateurs ont souhaité les commandesROLLBACKet/ouLOCK TABLESafin de gérer des identifiant uniques pour certaines tables. Ils peuvent être gérés bien plus efficacement en utilisant une colonne de type

AUTO_INCREMENT, en corrélation avec la fonctionLAST_INSERT_ID()ou la fonction Cmysql_insert_id(). See Section 12.8.3, « Fonctions d'informations ». SeeSection 24.2.3.33, «mysql_insert_id()».

Vous pouvez éviter le verrouillage de ligne. Certaines situations le requièrent vraiment, mais elles sont rares. Les tablesInnoDB supportent le verrouillage de ligne. Avec les tablesMyISAM, vous pouvez utiliser une colonne de type sémaphore, et faire ceci :

UPDATE tbl_name SET row_flag=1 WHERE id=ID;

MySQL retournera 1 pour le nombre de lignes affectées si la ligne a été trouvée, carrow_flagne vaut pas déjà 1 dans la ligne originale.

Vous pouvez comprendre la requête ci-dessus comme si le serveur MySQL avait utilisé la commande suivante :

UPDATE tbl_name SET row_flag=1 WHERE id=ID AND row_flag <> 1;

1.5.5.4. Procédures stockées et triggers

Les procédures stockées sont implémentées en version 5.0. SeeChapitre 19, Procédures stockées et fonctions.

Un trigger est une procédure stockée qui est activée lorsqu'un événement particulier survient. Par exemple, vous pouvez installer une Informations générales

procédure stockée qui est déclenchée dès qu'une ligne est effacée dans une table d'achat, pour que le client soit automatiquement effacé si tous ses achats sont effacés.

1.5.5.5. Les clés étrangères

En MySQL version 3.23.44 et plus récentes, les tablesInnoDBsupportent les vérifications d'intégrité référentielles. SeeChapitre 15, Le moteur de tablesInnoDB. Pour les autres types de tables, le serveur mySQL accepte la syntaxeFOREIGN KEYdans la commande CREATE TABLE, mais ne la prend pas en compte.

Pour les autres moteurs de stockage queInnoDB, MySQL analyse la clauseFOREIGN KEYde la commandeCREATE TABLE, mais ne l'utilise pas et ne la stocke pas. Dans le futur, l'implémentation va stocker cette information dans le fichier de spécifications de tables, pour qu'elle puisse être lue parmysqldumpet ODBC. Ultérieurement, les contraintes de clé étrangères seront incluses dans les tables MyISAM.

Voici des avantages aux contraintes de clés étrangères :

• En supposant que les relations soient proprement con¸ues, les clés étrangères rendent plus difficile pour un programmeur d'insérer des valeurs incohérentes dans la base.

• La vérification centralisée de contraintes par le serveur de base de données rend inutiles l'application de ces vérifications du coté de l'application. Cela élimine la possibilité que d'autres applications ne fassent pas les vérifications de la même fa¸on que les autres.

• L'utilisation des modifications et effacement en cascade simplifie le code du client.

• Les règles de clés étrangères proprement con¸ues aident à la documentation des relations entre les tables.

Gardez bien en tête que ces avantages ont un coût supérieur pour le serveur de bases, qui doit effectuer les tests. Les vérifications supplémentaires affectent les performances, ce qui est parfois suffisamment rebutant pour des applications qui les éviteront. Certaines applications commerciales ont placé la logique de vérification dans l'application, pour cette raison.

MySQL donne aux développeurs de bases de données le choix de leur approche. Si vous n'avez pas besoin des clés étrangères, et que vous voulez éviter leur surcoût, vous pouvez choisir un autre type de table, commeMyISAM. Par exemple, les tablesMyISAMsont extrêmement rapides pour les applications qui font essentiellement des opérationsINSERTetSELECT, car elles peuvent être utilisées simultanément. SeeSection 7.3.2, « Problème de verrouillage de tables ».

Si vous décidez de ne pas tirer avantage des contraintes d'intégrité, vous devez garder en tête ces conseils :

• En l'absence de vérification du coté du serveur, l'application doit se charger de ces vérifications. Par exemple, elle doit s'assurer que les lignes sont insérées dans le bon ordre, et que les lignes ne sont pas orphelines. Il faut aussi pouvoir rattraper une erreur au milieu d'une opération multiple.

• Si la clauseON DELETEest la seule fonctionnalité nécessaire, notez que depuis MySQL version 4.0, vous pouvez utiliser des commandesDELETEmulti-tables pour effacer les lignes dans plusieurs tables en une seule commande. SeeSection 13.1.1,

« Syntaxe deDELETE».

• Un palliatif au manque deON DELETEest d'ajouter la commandeDELETEappropriée lorsque vous effacez des lignes dans une table qui dispose d'une clé étrangère. En pratique, c'est souvent plus rapide que d'utiliser les clés étrangères, et c'est plus portable.

Soyez conscient que l'utilisation des clés étrangères dans certaines circonstances peuvent conduire à des problèmes :

• Les clés étrangères règlent des problèmes de cohérence, mais il est nécessaire de concevoir les contraintes correctement, pour éviter les contraintes circulaires, ou des cascades d'effacements incorrects.

• Il n'est pas exceptionnel pour un administrateur de créer une topologie de relations qui rende difficile la restauration de bases à partir d'une sauvegarde. MySQL résout ce problème en vous permettant de désactiver temporairement les contraintes. SeeSection 15.7.4,

« Contraintes de clés étrangèresFOREIGN KEY». Depuis MySQL 4.1.1,mysqldumpgénère un fichier d'export qui exploite cette possibilité de désactivation automatique à l'import.

Notez que les clés étrangères SQL sont utilisées pour assurer la cohérence des données, et non pas pour joindre des tables. Si vous voulez obtenir des résultats de tables multiples dans une commandeSELECT, vous devez le faire avec une jointure :

SELECT * FROM t1, t2 WHERE t1.id = t2.id;

SeeSection 13.1.7.1, « Syntaxe deJOIN». SeeSection 3.6.6, « Utiliser les clefs étrangères ».

La syntaxeFOREIGN KEYsansON DELETE ...est souvent utilisée par les applications ODBC pour produire automatiquement des clausesWHERE.

1.5.5.6. Les vues

Il est prévu d'implémenter les vues dans la version 5.0 ou 5.1 du serveur MySQL.

Historiquement, MySQL a été utilisé dans des applications et sur les systèmes Web, où l'auteur de l'application a un contrôle complet sur le système de base de données. L'utilisation a évolué au cours du temps, et de nombreux utilisateurs pensent maintenant que c'est important.

Les vues anonymes (tables dérivées, une sous-requête de la clauseFROMde la commandeSELECT) sont déjà disponibles en version 4.1.

Les vues sont la plupart du temps utiles pour donner accès aux utilisateurs à un ensemble de relations représentées par une table (en mode inaltérable). Beaucoup de bases de données SQL ne permettent pas de mettre à jour les lignes dans une vue, vous devez alors faire les mises à jour dans les tables séparées. SeeSection 5.5, « Règles de sécurité et droits d'accès au serveur MySQL ».

De nombreuses bases de permettent pas les modifications de vues, mais permettent les mises à jour dans des tables individuelles. Lors de la conception de notre système de vues, nous envisageons le support complet de la règle ``numéro 6 de Codd'' (autant que possible en SQL) : toutes les vues qui sont théoriquement modifiables, et doivent l'être en pratique.

1.5.5.7. ' -- ' comme début de commentaire

Certaines bases de données SQL utilisent '--' comme début de commentaire. Le serveur MySQL utilise ‘#’. Vous pouvez aussi utiliser la syntaxe du langage C/* ceci est un commentaire */. SeeSection 9.5, « Syntaxe des commentaires ».

MySQL version 3.23.3 et plus récent supporte les commentaires de type '--', si ce commentaire est suivi d'un espace. Ceci est dû au fait que ce type de commentaire a causé beaucoup de problèmes avec les requêtes générées automatiquement, qui contiennent du code tel que celui-ci, où nous insérons automatiquement la valeur du paiement dans la table!payment!:

UPDATE tbl_name SET credit=credit-!payment!

Pensez à ce qui se passe lorsque la valeur depaymentest négative, comme-1:

UPDATE account SET credit=credit--1

credit--1est une expression légale en SQL mais--est interprété comme un commentaire et la fin de l'expression est ignorée. Le résultat est que la commande prend une signification complètement différente :

UPDATE account SET credit=credit

La commande ne produit aucun changement! Cela montre que l'utilisation des commentaires de type '--' peuvent avoir des conséquences graves.

En utilisant notre implémentation des commentaires avec le serveur MySQL version 3.23.3 et plus récent,1-- ceci est un commentairene pose pas ce type de problème.

Une autre fonctionnalité supplémentaire est que le client en ligne de commandemysqlsupprime toutes les lignes qui commencent par '--'.

Les informations suivantes sont destinées aux utilisateurs de MySQL avec des versions antérieures à la version 3.23.3 :

Si vous avez un programme SQL dans un fichier texte qui contient des commentaires au format '--', il est recommandé d'utiliser l'utilitairereplacepour assurer la conversion en caractères ‘#’ :

shell> replace " --" " #" < text-file-with-funny-comments.sql \

| mysql database

Informations générales

au lieu du classique :

shell> mysql database < text-file-with-funny-comments.sql

Vous pouvez aussi éditer le fichier de commande ``lui-même'' pour remplacer les commentaires '--' par des commentaires ‘#’ :

shell> replace " --" " #" -- text-file-with-funny-comments.sql

Puis, rétablissez-les avec :

shell> replace " #" " --" -- text-file-with-funny-comments.sql