1. Trang chủ
  2. » Công Nghệ Thông Tin

Pratique de MySQL et PHP- P52 pps

5 137 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 5
Dung lượng 146,02 KB

Nội dung

5.3 Portabilité multi-SGBD 233 5.3 PORTABILITÉ MULTI-SGBD Nous abordons maintenant la question de la portabilité sur plusieurs systèmes de bases de données. Le présent livre est principalement orienté vers MySQL, mais ce produit lui-même s’attache à respecter la norme SQL, ce qui ouvre la perspective de pouvoir porter une application sur d’autres SGBD. Pour un site spécifique, installé en un seul exemplaire, avec le choix définitif d’utiliser MySQL, la question de la portabilité ne se pose pas. À l’autre extrême un logiciel généraliste que l’on souhaite diffuser le plus largement possible gagnera à être compatible avec des systèmes répandus comme PostgreSQL, ORACLE, voire SQLite. SQLite est une interface SQL pour stocker et rechercher des données dans un fichier, sans passer par un serveur de bases de données. SQLite est fourni avec PHP 5 et ne nécessite donc aucune installation autre que celle de PHP. Le site W EBSCOPE est conçu (et testé) pour être portable, ce qui impose quelques précautions initiales discutées ici. MySQL est un SGBD relationnel. Il appartient à une famille de systèmes très répandus – ORACLE, PostgreSQL, SQL Server, SYBASE, DB2, le récent SQLite – qui tous s’appuient sur le modèle relationnel de représentation et d’interrogation des données, modèle dont la principale concrétisation est le langage SQL. En théorie, toute application s’appuyant sur un SGBD relationnel est portable sur les autres. En pratique, chaque système ajoute à la norme SQL ses propres spécificités, ce qui nécessite, quand on veut concevoir une application réellement portable, de bien distinguer ce qui relève de la norme et ce qui relève des extensions propriétaires. Cette section décrit les écueils à éviter et donne quelques recommandations. Le site proposé dans les chapitres qui suivent s’appuie sur ces recommandations pour proposer un code entièrement portable. La seule modification à effectuer pour passer d’un système à un autre est un simple changement de paramètre de configuration. Comme nous allons le voir, le développement d’une application portable n’est pas plus difficile que celle d’une application dédiée, à condition de mettre en place quelques précautions initiales simples. Cette section peut être omise sans dommage par ceux qui n’envisagent pas d’utiliser un autre système que MySQL. 5.3.1 Précautions syntaxiques Il faut bien distinguer deux parties dans SQL. Le langage de définition de données, ou LDD, permet de créer tous les composants du schéma – principalement les tables. Les commandes sont les CREATE, ALTER,etDROP. Le langage de manipulation de données (LMD) comprend les commandes SELECT, UPDATE, INSERT et DELETE. MySQL est très proche de la norme SQL, et tout ce que nous avons présenté jusqu’ici, à quelques exceptions près, relève de cette norme et peut fonctionner sous un autre SGBD. Ces exceptions sont : 1. certains types de données, dont, principalement, TEXT ; 234 Chapitre 5. Organisation du développement 2. des constructions comme ENUM et SET ; 3. l’auto-incrémentation des clés (option AUTO_INCREMENT de CREATE TABLE). Il suffit d’ignorer ENUM et SET. Pour les types de données, MySQL propose un ensemble plus riche que celui de la norme SQL. Le tableau 2.1, page 462, donne la liste des types disponibles et précise ceux qui appartiennent à la norme SQL ANSI : il faut se limiter à ces derniers pour une application portable. Cela étant, certains types très pratiques, comme TEXT, ne sont pas normalisés (ou, plus précisément, la norme SQL qui préconise BIT VARYING n’est pas suivie). Il est souvent nécessaire d’utiliser ce type car les attributs de type VARCHAR sont limités à une taille maximale de 255 caractères. Le type TEXT existe dans PostgreSQL, mais pas dans ORACLE où son équivalent est le type LONG. Le script de création de notre schéma, Films.sql, page 202, est entièrement compatible avec la norme, à l’exception du résumé du film, de type TEXT, qu’il faut donc remplacer par LONG si l’on souhaite utiliser ORACLE. Ce genre de modification affecte l’installation, et pas l’utilisation du site, ce qui limite les inconvénients. Un type normalisé en SQL, mais assez difficile d’utilisation est le type DATE.Dans le cadre d’une application PHP, le plus simple est de stocker les dates au format dit « Unix », soit un entier représentant le nombre de secondes depuis le premier janvier 1970. Des fonctions PHP (notamment getDate()) permettent ensuite de manipuler et d’afficher cette valeur à volonté. Pour les mots-clés de SQL et les identificateurs, il n’y a pas de problème si on se limite aux caractères ASCII (mieux vaut éviter les lettres accentuées). L’utilisation des majuscules et minuscules est en revanche un point délicat. Les mots-clés SQL ne sont pas sensibles à la casse, et il en va de même des identificateurs. Pour un système relationnel, toutes les syntaxes suivantes seront donc acceptées, quelle que soit la casse employée pour créer le schéma : • SELECT TITRE FROM FILM ; • select titre from film ; • Select Titre From Film. Attention cependant à MySQL qui stocke chaque table dans un fichier dont le nom est celui donné à la table dans la commande CREATE TABLE. Sous un système UNIX où les noms de fichiers sont sensibles à la casse, MySQL ne trouvera ni la table FILM ni la table film si le fichier s’appelle Film. Il faut donc toujours nommer les tables de la même manière dans la clause FROM, ce qui est facilité par l’emploi d’une convention uniforme comme – par exemple – une majuscule pour la première lettre et des minuscules ensuite. Il faut de plus prendre en compte PHP qui, lui, est sensible à la casse dans les noms des variables. Les variables $TITRE, $titre et $Titre sont donc considérées comme différentes. Ces noms de variables sont attribués automatiquement par les fonctions PHP d’accès aux bases de données comme mysql_fetch_object() (MySQL), pg_fetch_object() (PostgreSQL), oci_fetch_object() (ORACLE), etc. Tout 5.3 Portabilité multi-SGBD 235 dépend de la manière dont ces fonctions nomment les attributs dans les résultats. Or les systèmes appliquent des règles très différentes : • MySQL utilise la même casse que celle de la clause SELECT : après un SELECT Titre FROM Film on récupèrera donc une variable $Titre ; • PostgreSQL utilise toujours les minuscules, quelle que soit la casse employée : après un SELECT Titre FROM Film on récupèrera donc une variable $titre ; • ORACLE utilise toujours les majuscules, quelle que soit la casse employée : après un SELECT Titre FROM Film on récupèrera donc une variable $TITRE. Ces différentes conventions sont dangereuses car elle influent directement sur la correction du code PHP. Avec l’apparition de la couche PDO qui uniformise l’accès aux bases de données depuis la version PHP 5.1, le problème est plus facile à résoudre, mais il est préférable dès le départ d’adopter des noms dattributs loù la casse n’est pas significative : nous avons choisi d’utiliser uniquement les minuscules. Dernier point auquel il faut être attentif : l’échappement des chaînes de caractères pour traiter les caractères gênants (typiquement, les apostrophes) avant une insertion ou une mise à jour. On utilise traditionnellement la fonction addSlashes() qui convient pour MySQL et PostgreSQL, mais par pour ORACLE, SQLite ou SYBASE qui utilisent le doublement des apostrophes. Il faut donc encapsuler la technique d’échappement dans une fonction qui se charge d’appliquer la méthode appropriée en fonction du SGBD utilisé (c’est la méthode prepareChaine() de notre classe BD). 5.3.2 Le problème des séquences Voyons maintenant le problème de l’incrémentation automatique des identifiants. Il est très fréquent d’utiliser comme clé primaire d’une table un numéro qui doit donc être incrémenté chaque fois que l’on insère une nouvelle ligne. En l’absence d’un mécanisme spécifique pour gérer ce numéro, on peut penser à prendre le numéro maximal existant et à lui ajouter 1. En SQL cela s’exprime facilement comme ceci : SELECT MAX(id) + 1 FROM < table> −− puis insertion dans la table avec le numéro obtenu Cette solution n’est pas très satisfaisante. Il faut en effet s’assurer que deux sessions utilisateur ne vont pas simultanément effectuer la requête donnant le nouvel id, sous peine de se retrouver avec deux commandes INSERT utilisant le même identifiant. On peut verrouiller la table avant d’effectuer la requête SELECT,auprixd’un blocage temporaire mais général, y compris pour les sessions qui ne cherchent pas à créer d’identifiant. Enfin, dernier inconvénient, cela peut soulever des problèmes de performances. Tous les systèmes fournissent donc des générateurs d’identifiants, ou séquences. Malheureusement aucun n’applique la même méthode. Dans MySQL, on peut asso- cier une option AUTO_INCREMENT à une clé primaire (voir par exemple page 199). 236 Chapitre 5. Organisation du développement Si on n’indique pas cette clé dans une commande INSERT, MySQL se charge auto- matiquement d’attribuer un nouvel identifiant. De plus il est possible de récupérer l’identifiant précédemment attribué avec la fonction last_insert_id().SQLite emploie la même méthode, sans spécifier AUTO_INCREMENT. Sous ORACLE et PostgreSQL, on utilise des séquences 5 qui sont des composants du schéma dédiés à la génération d’identifiants. Une séquence est créée par la commande DDL suivante : CREATE SEQUENCE <nomS´equence>; Il existe, pour chaque système, de nombreuses options permettant d’indiquer la valeur initiale, la valeur maximale, le pas d’incrémentation, etc. Sous PostgreSQL, on peut obtenir un nouvel identifiant en appliquant la fonction NEXTVAL() àla séquence. Ensuite, dans la même session, on obtient l’identifiant qui vient d’être attribué avec la fonction CURRVAL(). Voici un exemple de session sous PostgreSQL. On crée la séquence, on appelle deux fois NEXTVAL() puis une fois CURRVAL(). Films=# CREATE SEQUENCE ma_sequence; CREATE SEQUENCE Films=# SELECT NEXTVAL(’ma_sequence’); nextval 1 Films=# SELECT NEXTVAL(’ma_sequence’); nextval 2 Films=# SELECT CURRVAL(’ma_sequence’); currval 2 Le fonctionnement est pratiquement identique sous ORACLE. Pour obtenir, dans une application PHP, un générateur d’identifiants qui fonctionne sur tous les SGBD, il faut donc écrire une fonction (ou une méthode dans une classe) qui fait appel, selon le système utilisé, à la méthode appropriée. En ce qui concerne MySQL, si on souhaite que l’application soit portable, on ne peut pas utiliser l’auto-incrémentation des lignes de la table ; il faut donc se ramener aux séquences trouvées dans les autres systèmes. On y arrive aisément en créant une table spéciale, avec un seul attribut auto-incrémenté. Chaque insertion dans cette table génère un nouvel identifiant que l’on peut alors obtenir avec la fonction last_insert_id(). Voici, sous MySQL, une session équivalente à celle de PostgreSQL. 5. PostgreSQL fournit également un type non standard SERIAL qui fonctionne comme l’auto- incrémentation de MySQL. 5.3 Portabilité multi-SGBD 237 mysql> CREATE TABLE SequenceArtiste -> (id INTEGER NOT NULL AUTO_INCREMENT, -> PRIMARY KEY (id)); mysql> mysql> insert into SequenceArtiste values(); Query OK, 1 row affected (0,01 sec) mysql> insert into SequenceArtiste values(); Query OK, 1 row affected (0,00 sec) mysql> select last_insert_id(); + + | last_insert_id() | + + |2| + + La classe BD, décrite dans le chapitre 3, est enrichie d’une méthode abstraite genereID(), déclarée comme suit : // G´en´eration d’un identifiant abstract public function genereID($nomSequence); Cette méthode est ensuite déclinée dans chaque sous-classe correspondant à chaque système. Voici la méthode pour MySQL. // G´en´eration d’un identifiant public function genereID($nomSequence) { // Insertion d’un ligne pour obtenir l’auto-incr´ementation $this->execRequete("INSERT INTO $nomSequence VALUES()"); // Si quelque chose s’est mal pass´e, on a lev´e une exception, // sinon on retourne l’identifiant return mysql_insert_id(); } Et la voici pour PostgreSQL. // G´en´eration d’un identifiant public function genereID($nomSequence) { // Appel `alas´equence $res = $this->execRequete("SELECT NextVal(’$nomSequence’) AS id"); $seq = $this->objetSuivant($res); return $seq->id; } La gestion des séquences est le seul aspect pour lequel la programmation d’une application PHP/MySQL s’écarte légèrement des techniques que l’on emploierait si . CREATE, ALTER,etDROP. Le langage de manipulation de données (LMD) comprend les commandes SELECT, UPDATE, INSERT et DELETE. MySQL est très proche de la norme SQL, et tout ce que nous avons présenté jusqu’ici,. et SET ; 3. l’auto-incrémentation des clés (option AUTO_INCREMENT de CREATE TABLE). Il suffit d’ignorer ENUM et SET. Pour les types de données, MySQL propose un ensemble plus riche que celui de. est de stocker les dates au format dit « Unix », soit un entier représentant le nombre de secondes depuis le premier janvier 1970. Des fonctions PHP (notamment getDate()) permettent ensuite de

Ngày đăng: 06/07/2014, 00:20

TỪ KHÓA LIÊN QUAN