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

Pratique de MySQL et PHP- P52 pps

5 137 0
Tài liệu đã được kiểm tra trùng lặp

Đ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

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

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

Trang 1

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 WEBSCOPEest 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, et DROP 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 ;

Trang 2

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 ó 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 ó 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

Trang 3

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 ló 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( i d ) + 1 FROM < t a b l e >

−− p u i s i n s e r t i o n d a n s l a t a b l e a v e c l e numéro o b t e n u

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, au prix d’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)

Trang 4

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équences5 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.

Trang 5

mysql> CREATE TABLE SequenceArtiste

-> (id INTEGER NOT NULL AUTO_INCREMENT,

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() |

+ -+

+ -+

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 ` a la s´ 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

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

TỪ KHÓA LIÊN QUAN