Tutoriel MySQL
Tutoriel MySQL
Tutoriel MySQL
Le fondement de notre univers digital est une montagne de données sans cesse en
expansion. Les systèmes de gestion de bases de données tels que MySQL sont des éléments
centraux de la Toile et du monde connecté. Ces derniers permettent de traiter une grande
quantité de données en ligne et de manière durable. Des ensembles de données complexes
sont découpés en sous-ensembles maniables et sont mis en relation si besoin pour cela.
Nous allons vous présenter les fondements de la gestion de base de données dans notre
tutoriel MySQL et vous montrer des exemples de la façon dont vous pouvez optimiser le
stockage de données pour votre projet Web avec MySQL.
Sommaire
1. Qu’est-ce que MySQL?
2. Installation du système de gestion de base de données
3. Gestion de bases de données avec phpMyAdmin
4. Etablir la connexion de base de données
5. Requêtes de données avec SELECT, INSERT, UPDATE et DELETE
6. Prepared Statements
7. Fonctions de date et d’heure dans MySQL
8. Rapports d’erreurs MySQL
9. JOIN
10. De débutant à professionnel
1
Fait
l’abréviation SQL signifie « Structured Query Language », un langage informatique servant à
l’administration de structures de bases de données. Les opérations possibles comprennent des
requêtes, des insertions, mises à jour et suppressions de fichiers de données.
2
• La base de données : une base de données est une base de données relative au
contenu tel que les données relatives aux clients (CMS). Un DBMS peut gérer
plusieurs bases de données en même temps.
Le graphique suivant sert de représentation schématique d’un système de gestion de base de
données:
Un système de bases de données est composé d’un système de gestion de bases de données
et de nombreuses bases de données.
3
Tous les tableaux d’une base de données relationnelle se composent de colonnes et de
lignes. Chaque colonne d’un tableau renvoie à un attribut précis. Dans le tableau auteurs se
trouvent par exemple les attributs id, prénom et nom de famille. Les lignes d’un tableau sont
caractérisées de rangées comportant chacune un ensemble de données. Ce dernier est en
général identifié (numéroté) clairement à travers une clé primaire. On définit lors de la
conception du tableau quel attribut fait fonction de clé primaire. La condition pour cela est
que la clé primaire permette un classement clair. Une clé primaire ne peut pour cette raison
être utilisée qu’une seule fois au sein d’une colonne. Une numérotation avec
des IDs (identifiants) est recommandée.
Le tableau oeuvres, en dehors du fait d’intégrer la clé primaire oeuvres_id, contient aussi
des clés étrangères comme auteurs_id. Ce tableau établit une relation entre les deux
tableaux et permet de nouer les articles d’un tableau avec ceux des autres. On parle
d’un join (jointure) lorsqu’on met en contact deux tableaux d’une base de données
relationnelle. Une telle jointure peut par exemple induire la requête suivante : « Charger
toutes les valeurs de l’auteur John Ronald Reue Tolkien incluant la date de première
publication ».
Tolkien est listé dans le tableau auteurs avec la clé primaire auteurs_id1. Pour extraire ces
valeurs de l’auteur, des valeurs de clés étrangères entrent en jeu. Toutes les rangées reliées à
auteurs_id1 sont ici chargées.
Dans la pratique, les opérations de bases de données MySQL sont réalisées avec
des commandes SQL standardisées telles que SELECT, INSERT, UPDATE et DELETE. Nous
aborderons plus en détail ce sujet dans les chapitres suivants de notre tutoriel MySQL.
Vous pouvez bien sûr stocker toutes les données à la fois dans un seul tableau (les auteurs et
leurs œuvres). Une telle gestion de données entraîne cependant de nombreuses
redondances supplémentaires, étant donné que les colonnes « prénom » et « nom »
devraient plutôt être saisies comme une seule donnée dans ce cas précis. Une telle
redondance consomme de la mémoire, mais signifie également que toutes les mises à jour
doivent être faites à différents niveaux de la base de données. Lorsque vous travaillez avec
4
des bases de données relationnelles, il convient de ne déterminer qu’un seul motif par
tableau. On parle dans ce cas de normalisation des données.
Le champ d‘application central de MySQL est le stockage de données dans le cadre d’offres
Web dynamiques. La combinaison de MySQL avec le logiciel de serveur Web Apache et le
langage script PHP ou Perl s’est établie comme le squelette de base dans tout
développement Web. Cette pile de programmes Web peut être utilisé comme LAMP (Linux),
MAMP (Mac OS) ou WAMP (Windows) avec les différents principaux systèmes d’exploitation.
Nous recommandons l’environnement texte local XAMPP aux débutants avec MySQL pour
une première expérience avec le système de gestion de base de données. Ce dernier se
trouve dans la version actuelle de MariaDB.
5
navigateur Web. Connaître les commandes SQL appropriées n’est initialement pas
nécessaire.
Charger phpMyAdmin
Une fois l’ensemble de logiciels XAMPP installé, démarrez le système de gestion de base de
données (MySQL ou MariaDB) de manière similaire aux autres composants des test-stacks
via le panneau de configuration. Utilisez pour cela le bouton « Start » ou démarrer sous
« Actions ». Afin de charger phpMyAdmin via le navigateur Web, vous devez également
redémarrer le serveur Web Apache. Les modules activés apparaissent en vert sur le panneau
de configuration XAMPP. Vous obtenez de plus l’état actuel des modules XAMPP par
messagerie.
Démarrez MySQL ainsi que le serveur http Apache via le panneau de configuration XAMPP
Fait
XAMPP a été conçu dans le cadre du projet de logiciel Apache Friends en tant que système
de test compact pour une mise en œuvre sur un ordinateur local. La suite de logiciels n’est
n’a ainsi pas été prévue pour mettre des services Web à disposition sur Internet. XAMPP n’est
donc pas adapté en tant que système de production en raison de nombreuses limitations
dans le domaine de la sécurité.
Vous trouverez le mode de test local de l’interface Web du programme
d’administration http://localhost/phpmyadmin/.
Après avoir défini un mot de passe pour le compte racine (root-Account) lors de l’installation
de MySQL, phpMyAdmin demande ces données d’identification via une fenêtre prévue à cet
effet. Si vous utilisez phpMyAdmin dans le cadre d’un produit d’hébergement Web, les
données de connexion appropriées sur le fournisseur seront attribuées. Vous ne disposez en
général pas des droits racine dans ce cas.
6
Après une connexion réussie, phpMyAdmin vous présente la page d’accueil de l’application.
Celle-ci vous offre la possibilité de modifier les paramètres de base de la police de la
connexion MySQL ainsi que de choisir les modalités d’affichage (langue, design, et taille de la
police). Vous trouverez également un aperçu des paramètres de base de votre serveur de
base de données, le logiciel de serveur Web utilisé ainsi que des informations sur la version
actuelle de phpMyAdmin sur la partie droite. La barre de menu de la page d’accueil est
conçue comme toutes les autres barres de menus de l’application, sous la forme d’onglets.
Vous avez le choix entre les onglets, base de données, SQL, état, comptes utilisateurs,
importation, exportation, paramètres, et autres.
7
Les bases de données se trouvent dans l’onglet « Databases » avec phpMyAdmin
Choisissez un nom pour votre base de données dans le champ « Create database » (créer
une nouvelle base de données). Nous recommandons la police utf8mb4_unicode_ci. Le choix
de cette dernière permet d’indiquer au serveur de base de données quel codage appliquer
pour l’envoi et la réception de données. Les variantes mb4 permettent aussi des caractères
exotiques tels que des symboles ou des emojis, sortant du niveau de base Unicode (plan
multilingue de base), et sont donc recommandées.
Afin de créer une base de données, choisissez un nom et déterminez une police sous-jacente
Confirmez votre saisie en cliquant sur « Create » (créer). La base de données ainsi créée
apparaît désormais sur le panneau de navigation sur le côté gauche de l’écran. Les bases de
données nouvellement créées ne contiennent pas de contenu initialement. Afin d’ajouter des
données, créez un tableau lors de l’étape suivante.
8
Concevoir des tableaux
Pour concevoir un nouveau tableau, choisissez la base de données souhaitée et rendez-vous
sur l’onglet « structure » de la barre de menu.
Colonne Description
9
Colonne Description
Pour établir un tel tableau utilisateurs (users), créez sept colonnes. Vous pouvez valider la
saisie en cliquant sur « Go ».
10
Le tableau suivant vous donne une description de la structure des tableaux et des formats
possibles.
Option Description
Name Chaque colonne d’un tableau de base de données se voit attribuer un nom. Des
restrictions peuvent y être ajoutées. Les caractères latins (en majuscule ou
minuscule, mais sans tréma), les chiffres, les icones des différentes monnaies, et
tirets ne posent aucun problème pour cela. Ces derniers peuvent être utilisés
comme alternative aux espaces vides non autorisés (faux : user id; correct :
user_id). Les noms de colonnes ne doivent pas contenir que des chiffres. Par
ailleurs, il existe divers mots-clés réservés pour différentes tâches dans le langage
de base de données SQL. Une liste se trouve dans la documentation mySQL. Vous
pouvez contourner la plupart de ces restrictions mais vous devez mettre la colonne
respective entre guillemets pour ce faire. Les mêmes règles sont aussi valables pour
les. Nous vous recommandons d’utiliser des noms de colonnes clairs qui
correspondent à l’attribut respectif.
Type Le type de données spécifie quel type de données est stocké dans une colonne.
MySQL et MariaDB vous permettent de définir des données comme des nombres
entiers à virgule flottante, l’heure et la date ainsi que des chaînes de texte et des
données binaires. Une description se trouve dans le tableau des types de données.
Length/values Avec certains types de données (par exemple des chaînes de caractères) vous
pouvez affecter des valeurs pour la longueur maximale d’une colonne. Ceci est
facultatif.
Default L’option « Default » vous permet de définir une valeur standard pour une colonne.
Celle-ci est toujours automatiquement ajoutée lorsqu’un paquet de données ne
contient pas de valeur pour la colonne respective.
Collation Avec l’option « Collation », vous définissez un type de caractères particulier pour
une colonne, pouvant différer des paramètres de bases globaux de bases de
données. Vous pouvez modifier le codage au niveau du tableau pour toutes les
colonnes.
Attributes Certains types de données peuvent être déterminés de manière plus détaillée par
attributs facultatifs. Vous pouvez par exemple ainsi spécifier avec les attributs
signed et unsigned, si un nombre entier ou à virgule flottante peut aussi prendre
des valeurs négatives, et non uniquement positives.
Index Vous pouvez définir des règles d’indexation via l’option « Index ». Sélectionnez un
paramètre d’indexation PRIMARY pour une colonne. Ce dernier est considéré
comme la clé primaire du tableau. Le paramètre UNIQUE spécifie que les valeurs ne
11
Option Description
peuvent être stockées qu’une fois dans cette colonne. Ainsi, les duplications
peuvent être évitées si besoin.
Les options présentées ici sont les paramètres les plus importants pour le formatage de
colonnes. En utilisant la barre de défilement vers la droite, vous trouverez encore plus de
paramètres que nous ne pouvons décrire dans notre guide MySQL pour débutants.
Le tableau suivant répertorie les différents types de données qui peuvent être traitées avec
MySQL et MariaDB, ainsi que les différentes tranches de valeurs et de mémoire requise.
Besoin
de
Type Description Valeur mémoire
TINYINT Un nombre entier très faible Sans signe : 0 à 255 Avec signe : -128 1 Byte
à +127
SMALLINT Un nombre entier faible Sans signe : 0 à 65.535 Avec signe : - 2 Bytes
32.768 à +32.767
MEDIUMINT Un nombre entier moyen Sans signe : 0 à 16.777.215 Avec signe 3 Bytes
: -8.388.608 à +8.388.607
FLOAT Un nombre à virgule flottante Sans signe : 0 à 3,4e+38 Avec signe : - 4 Bytes
à précision simple 3,4e+38 à 3,4e+38
12
Besoin
de
Type Description Valeur mémoire
DOUBLE Un nombre à virgule flottante Sans signe : 0 à 3,4e+38 Avec signe : - 8 Bytes
avec double précision 3,4e+38 à 3,4e+38
13
Besoin
de
Type Description Valeur mémoire
BLOB Un BLOB (Binary Large Object) Longueur max : 65.535 Bytes M+2
est un objet binaire avec des Bytes
données à longueur variable
(des images ou fichiers audio
par exemple)
TINYBLOB Petit objet binaire avec des Longueur max M: 255 Bytes M+1
données à longueur variable Byte
MEDIUMBLOB Objet binaire moyen avec des Longueur Max M : 16.777.215 Bytes M+3
données à longueur variable Bytes
LONGBLOB Objet binaire grand avec des Longueur max : 4.294.967.295 Bytes M+4
données à longueur variable (4 GB). Bytes
Nous avons par exemple choisi les paramètres suivants pour le tableau « users » :
Les valeurs possibles pour la colonne ID ont été définies comme étant des nombres entiers
(nombre entier, INT) et portent l’attribut UNSIGNED. L’ID ne peut ainsi accepter que des
chiffres aux valeurs positives. Nous avons sélectionné le réglage PRIMARY pour ce qui est de
l’Index. Le numéro d’identification fonctionne donc comme une clé primaire pour le tableau
utilisateurs. Décocher la case a_i (AUTO_INCREMENT) signale au système de gestion de base
de données que les IDs doivent être générés automatiquement pour chaque entrée sous
forme de nombres consécutifs. Les valeurs des colonnes prénom, nom, email et mot de
passe ont été définies comme type de données VARCHAR. Il s’agit de chaînes de caractères
variables, dont la longueur (M) est limitée à 50 caractères avec l’option « Length/Value ».
14
L’option index UNIQUE est aussi activée pour la colonne email. Vous vous assurez ainsi que
toutes les adresses email ne soient enregistrées qu’une seule fois dans votre tableau.
Pour les colonnes created_at et updated_at, nous avons choisi le type de données
TIMESTAMP. Le système de gestion de base de données stocke les données temporelles lors
de la création et de l’actualisation de paquets au format AAAA-MM-JJ HH:MM:SS. Etant
donné que le système génère automatiquement un horodatage pour chaque nouvelle
entrée, nous choisissons pour la colonne created_at la valeur standard
CURRENT_TIMESTAMP par défaut. La colonne updated_at n’est pertinente que si nous
mettons à jour les entrées. Les valeurs nulles sont permises pour cette colonne, dotées de
la valeur standard NULL par défaut.
Fait
la valeur NULL représente une entrée vide avec PHP. Un champ de données possède la valeur
NULL si aucune valeur n’a été attribuée.
15
CREATE TABLE test.users ( id INT UNSIGNED NOT NULL AUTO_INCREMENT ,
forename VARCHAR(50) NOT NULL ,
surname VARCHAR(50) NOT NULL ,
email VARCHAR(50) NOT NULL ,
password VARCHAR(50) NOT NULL ,
created_at TIMESTAMP NOT NULL DEFAULT
CURRENT_TIMESTAMP,
updated_at TIMESTAMP NULL DEFAULT NULL ,
PRIMARY KEY (id),
UNIQUE (email))
ENGINE = InnoDB;
Vous trouverez une description détaillée de la syntaxe SQL dans le chapitre sur les requêtes
de bases de données.
Enregistrez vos paramètres en cliquant sur « save ». Le tableau utilisateurs s’affiche dans le
panneau de navigation sous la base de données de test.
Gérer des tableaux
Pour gérer un tableau créé, cliquez sur le nom du tableau dans le panneau de navigation.
phpMyAdmin vous affiche sur l’onglet « Browse » un aperçu du tableau respectif avec les
données enregistrées. Dans le cas de notre tableau exemple, la requête livre un résultat vide.
Il n’y a pas encore de paquets de données dans le tableau users.
16
Modifier la structure de tableaux
Si vous souhaitez compléter votre tableau en incluant des colonnes supplémentaires,
modifier ou supprimer des colonnes existantes, rendez-vous sur l’onglet « Structure ».
Complétez des colonnes via le bouton « Add columns », en spécifiant le nombre souhaité de
nouvelles colonnes et leur position respective.
Une nouvelle colonne est ajoutée selon updated_at dans l’exemple suivant :
17
Les colonnes sélectionnées sont traitées via un point de vue différent
Les modifications apportées à la structure du tableau peuvent conduire à la perte de
données dans certaines circonstances. Avant de traiter ou supprimer des colonnes de
tableaux déjà existantes, vous devriez dans tous les cas effectuer une sauvegarde de votre
base de données. Rendez-vous pour cela sur l’onglet « Export », choisissez le format de
données de votre choix pour la sauvegarde et confirmez en appuyant sur « Go ». Une fenêtre
s’ouvre, dans laquelle votre navigateur Web interroge l’espace de stockage cible pour le
téléchargement. Une alternative à la sauvegarde de bases de données via phpMyAdmin est
le programme de sauvegarde gratuit MySQLDumper.
Créer des entrées de tableaux
Pour remplir votre tableau avec phpMyAdmin avec des données, vous avez deux possibilités :
soit vous importez les paquets depuis un fichier externe (comme une sauvegarde par
exemple), soit vous créez les entrées du tableau manuellement. Pour ce faire, choisissez le
tableau exemple utilisateurs (users) et naviguez sur l’onglet « insert ».
phpMyAdmin vous affiche maintenant l’écran de saisie de données suivant :
18
Créer des entrées de tableaux via phpMyAdmin sur l’onglet « Insert »
Les colonnes définies pour le tableau utilisateurs sont listées sous « Column ». Vous
trouverez sous « Type » les informations sur le type de données pour les colonnes
respectives, ainsi que la limite de caractères entre parenthèses. Nous mettons
volontairement la partie « Function » entre parenthèses et passons directement à « Value ».
Dans ce domaine, on définit les valeurs pour certaines colonnes de notre tableau exemple.
Dans le chapitre précédent, nous avons configuré le tableau utilisateurs (users) de telle sorte
que les champs de données pour les colonnes ID, created_at et updated_at soient
automatiquement dotés de contenu par le système de gestion de base de données. Dans la
colonne ID nous attribuons via AUTO_INCREMENT un numéro d’identification pour chaque
nouvelle entrée en cours. Le champ created_at est automatiquement rempli via l’horodatage
actuel. Le système attribue ensuite pour updated_at la valeur par défaut NULL. Nous ne
devons ainsi que saisir les données pour les
colonnes forename, surname, email et password manuellement. Nous illustrons ceci avec
des données utilisateurs fictifs :
• Forename : John
• Surname : Doe
• Email : [email protected]
• Password : qwertz
19
Ajoutez les données à l’écran de saisie de données et confirmez avec « Go »
Cliquez sur « Go » pour transférer les données vers votre tableau. PhpMyAdmin passe
automatiquement à l’onglet « SQL » et indique l’opération de base de données effectuée en
tant que déclaration selon la syntaxe SQL :
INSERT INTO users (id, forename, surname, email, password, created_at, updated_at)
VALUES (NULL, 'John', 'Doe', '[email protected]', 'qwertz', CURRENT_TIMESTAMP,
NULL);
PhpMyAdmin vous donne des relevés pour chaque opération de base de données
20
En principe, toutes les opérations de bases de données peuvent être réalisées
confortablement via phpMyAdmin sur une interface graphique, mais aussi dans le langage de
base de données SQL. Ceci fait partie des procédures standard de développement Web.
Ces requêtes SQL se trouvent dans le code source de toutes les applications Web
dynamiques et permettent au serveur Web d’interagir avec la base de données. Le langage
de base de données SQL repose sur des commandes dont le but est par exemple de
récupérer des données et de les utiliser dans le cadre de l‘exécution du programme. Nous
abordons dans le chapitre suivant de notre tutoriel MySQL les principales commandes SQL, à
savoir SELECT, INSERT, DELETE et UPDATE ainsi que la syntaxe des opérations de bases de
données fondamentales.
Mais d’abord, remplissons notre tableau utilisateurs (users) avec d’autres données
utilisateurs et regardons la vue d’ensemble du tableau dans l’onglet « Browse » (Parcourir) :
Toutes les entrées du tableau sont triées selon la clé primaire dans l’aperçu de l’onglet «
Browse ».
Un clic sur le nom de la colonne respective trie le tableau dans l’ordre souhaité.
Etablir la connexion de base de données
Maintenant que nous avons rempli notre tableau exemple utilisateurs avec des entrées, nous
examinerons dans les chapitres suivants comment les données stockées via PHP peuvent
être consultées en utilisant un serveur Web Apache.
Il est pour cela demandé dès la première étape d’établir une connexion de base de données.
Trois interfaces sont disponibles : MySQL Extension, MySQL Improved Extension (MySQLi) et
PHP Data Objects (PDO).
21
• MySQL-Extension : MySQL-Extension est une interface MySQL qui était très
populaire, mais maintenant considérée comme obsolète. En comparaison avec
MySQLi et PDO, MySQL-Extension présente l’inconvénient qu’il ne supporte pas
les Prepared Statements , ni les paramètres désignés.
• MySQLi : MySQLi est une version améliorée de l’extension classique PHP pour l’accès
à des bases de données MySQL. L’interface fonctionne aussi bien de manière orientée
objet que de manière procédurale. L’utilisation est limitée aux bases de données
MySQL et MariaDB.
• PDO : PHP Data Objects (PDO) est une interface orientée vers l’objet qui fournit un
niveau abstrait pour l’accès aux données. Ainsi, les bases de données MySQL, mais
aussi d’autres systèmes tels que PostgreSQL, Oracle, MSSQL ou SQLite peuvent être
intégrés à PHP.
Nous nous limiterons par la suite aux connexions à la base de données via PDO.
Pour effectuer une demande avec une base de données dans le cadre d’un script PHP, il doit
d’abord être authentifié. Une connexion à la base de données par l’intermédiaire de PDO se
fait en utilisant la ligne de code suivante :
<?php
$pdo = new PDO('DSN', 'username', 'password');
?>
Il est recommandé d’ajouter ceci au début de chaque script contenant des opérations de
base de données.
Nous utilisons le mot de passe PHP new pour créer une instance de la classe de base PDO.
Son constructeur attend trois paramètres de base. Le Data Source Name (DSN) ainsi qu’un
nom d’utilisateur et un mot de passe pour la base de données. Le DSN comprend dans notre
cas les paramètres suivants :
• Pilote de base de données PDO : mysql
• Serveur de base de données (host=) : localhost
• nom de base de données (dbname=) : test
• Paquet (charset=): utf8
Si vous n’avez pas défini de données d’accès pour votre base de données, utiliser le nom
d’utilisateur root ainsi qu’un mot de passe vide :
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
?>
La connexion à la base de données est stockée dans la variable $pdo. Cela vous permet
d’établir la connexion dans les dernières étapes du code du programme.
22
Si une connexion à la base de données a été établie, vous pouvez envoyer un certain nombre
de requêtes à la base de données via le script de code. Terminez le script pour interrompre la
connexion à la base de données.
Définissez tout d’abord la commande SQL SELECT puis les colonnes et tableaux respectifs, sur
lesquels la commande doit fonctionner. Un point-virgule conclut ce Statement.
Vous avez également la possibilité d’étendre la déclaration (Statement) à une condition
facultative telle qu’un tri ou un regroupement :
SELECT colonne FROM tableau WHERE condition
ORDER BY données dans un ordre de tri;
Les commandes SQL sont conventionnellement en lettres majuscules, tandis que les bases de
données, tableaux et autres sont en minuscule. Cela s’explique uniquement pour des raisons
de lisibilité. SQL en principe un langage sans format et ne fait donc pas de distinction entre
les majuscules et les minuscules.
Si vous utilisez des noms de tableaux et de colonnes qui comportent déjà des mots-clés
prédéfinis (ce qui n’est pas recommandé), placez ces derniers entre guillemets.
Nous illustrons la syntaxe des SQL-Statements simples avec comme exemples les
commandes SELECT, INSERT, UPDATE et DELETE.
SELECT
Utilisez la commande SELECT pour récupérer les séries de données sélectionnées (rangées)
d’un nombre quelconque de tableaux. Si vous souhaitez par exemple utiliser les prénoms et
noms ainsi que les adresses email de tous les utilisateurs dans le tableau exemple créé
auparavant, créez un fichier PHP text.php dans le dossier htdocs de votre environnement
XAMPP et ajoutez le script suivant :
23
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "SELECT forename, surname, email FROM users";
foreach ($pdo->query($sql) as $row) {
echo $row['forename'] . " " . $row['surname'] . "<br />";
echo "E-Mail: " . $row['email'] . "<br /><br />";
}
?>
L’exemple de code se lit de la manière suivante : tout d’abord, nous commençons le script
avec la balise PHP-Start <?php. Dans la ligne deux, nous nous connectons à notre base de
données de test sur l’hébergeur local et nous la stockons dans la variable $pdo. Le Statement
SQL avec la commande SELECT se trouve sur la ligne trois. Ici, le système de gestion de base
de données indique de charger les colonnes forename, surname et email depuis le
tableau utilisateurs (users). Nous enregistrons ce Statement dans la variable $sql.
Les lignes 4 à 7 affichent une boucle foreach. Cela nous donne la possibilité de parcourir tout
tableau, par exemple, de passer par une structure de données progressivement. Nous
définissons entre parenthèses derrière la construction foreach les séries du tableau à itérer
et la façon dont les données demandées sont sauvegardées :
$pdo->query($sql) as $row
La variable $pdo porte sur la base de données désirée sur la ligne 2 de la connexion définie.
Nous l’envoyons avec la fonction query() de la variable $sql du Statement SQL.
Le serveur Web récupère ainsi les colonnes forename, surname et email du tableau
utilisateur depuis la base de données test et passe chaque ligne du tableau en
boucle foreach. Lorsque les données passées en revue sont stockées, le mot-clé PHP définit
la série variable $row.
Lors du premier passage de la boucle Foreach, le tableau apparaîtrait comme tel :
$row = array (
forename => John,
surname => Doe,
email => [email protected]
)
24
Nous passons en revue chaque ligne du tableau utilisateurs individuellement, lisons les
données stockées pour les colonnes définies dans le Statement SQL et les faisons passer sur
le navigateur Web.
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "SELECT * FROM users";
foreach ($pdo->query($sql) as $row) {
echo $row['forename'] . " " . $row['surname'] . "<br />";
echo "E-Mail: " . $row['email'] . "<br />";
echo "Created at: " . $row['created_at'] . "<br /><br />";
}
?>
25
Nous avons ainsi la possibilité d’utiliser toutes les données stockées dans le
tableau utilisateurs (users) dans le cadre du script. On peut observer sur la capture d’écran ci-
dessous l’ajout d’un horodatage :
26
Avec ORDER BY vous pouvez effectuer les tris de votre choix pour vos données
INSERT
La création d’entrées de bases de données se fait rarement manuellement via phpMyAdmin.
En règle générale, les données sont écrites dans le cadre de l’exécution du script à partir du
serveur Web de la base de données : si un internaute remplit par exemple un formulaire en
ligne sur un site Web ou s’il laisse un commentaire sur une boutique en ligne. Dans les deux
cas, la commande SQL INSERT est utilisée en arrière-plan. Le statement SQL avec la
commande INSERT sera créé selon le schéma suivant.
INSERT INTO tableau (colonne1, colonne2, colonne3) VALUES (valeur1,
valeur2, valeur3);
Cela se lit comme suit : chargement du tableau et ajout des valeurs 1, 2 et 3 aux tableaux 1, 2
et 3.
Un script PHP simple pour ajouter un autre paquet à notre tableau utilisateurs
(users) pourrait ressembler à ceci :
<?php
if ($pdo->exec($sql) === 1)
?>
27
Nous établissons tout d’abord la connexion à la base de données et enregistrons cette
dernière dans la variable $pdo. Nous définissons ensuite le Statement SQL et l’enregistrons
dans la variable $sql. Sur la ligne 5, nous utilisons la flèche (->) pour accéder à la
variable $pdo et exécuter le Statement SQL enregistré dans $sql à l’aide de la fonction exec().
Pour s’assurer que le script ajoute un paquet dans le tableau utilisateurs (users), nous
vérifions le nombre de lignes concernées à l’aide de la condition if. Cela garantit que le String
New Record a été créé avec succès et affiché via le navigateur Web, lorsque le nombre de
paquets ajouté est égal à 1. Si le script est à nouveau exécuté, le message est manquant. On
évite par ailleurs les doublons en définissant la valeur email avec l’attribut UNIQUE.
28
Un aperçu actualisé de votre tableau de données peut être chargé si besoin via phpMyAdmin
(les nouvelles données sont marquées en rouge)
UPDATE
Pour mettre à jour une des données existantes, utilisez la commande SQL UPDATE selon le
schéma suivant :
UPDATE tableau SET colonne1 = valeur1, colonne2 = valeur2
WHERE colonne3 = valeur3;
29
Nous définissons dans le Statement SQL que la valeur actuelle dans la colonne email doit
être remplacée par la nouvelle valeur [email protected], dans la mesure où la
colonne ID contient la valeur 1. Nous ne modifions ainsi que le paquet de données avec la clé
primaire 1. De plus, nous mettons à jour la valeur pour la colonne updated_at dans le même
SQL-Statement à l’aide de la fonction MySQL now(), qui indique l’horodatage actuel.
L’instruction SQL est exécutée comme précédemment avec la ligne de code $pdo-
>exec($sql) dans le cadre d’une condition if.
30
La fonction NOW () remplace le champ de données avec l’horodatage actuel updated_at (les
données actualisées sont marquées en rouge)
Dans cet exemple nous avons actualisé l’adresse email et remplacé la valeur standard NULL
dans la colonne updated_at par un horodatage. La commande UPDATE permet par ailleurs
de transférer des valeurs d’une colonne à l’autre. Cette opération peut par exemple être
utilisée lorsqu’on veut élargir le tableau utilisateurs avec la colonne email_registration. Cela
nous donne la possibilité de faire la distinction entre les deux adresses email : celle utilisée
lors de l’enregistrement, et celle de contact actuelle, qui peut changer au fil du temps.
Cependant, les deux adresses sont initialement les mêmes, afin que les valeurs d’un champ
puissent être transmises à l’autre. Nous ajoutons pour ce faire les nouvelles
colonnes email_registration avec phpMyAdmin via « Add columns » dans l’onglet
« Structure » :
Ajoutez de nouvelles colonnes de tableau là où vous le souhaitez via Add columns dans
l’onglet structure.
Pour transmettre les valeurs, nous utilisons le Statement UPDATE suivant :
UPDATE users SET email_registration = email
Etant donné que nous voulons mettre à jour tous les paquets de données, nous ne formulons
pas de condition de mise à jour.
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "UPDATE users SET email_registration = email";
$affected = $pdo->exec($sql);
echo "$affected rows updated<br>";
?>
31
Si le script est exécuté via le serveur Web, le système de gestion de base de données
transmet les valeurs de la colonne à tous les paquets de données dans la colonne
email_registration.
Le script transmet toutes les valeurs de la colonne email dans la colonne email-registration et
indique le nombre de colonnes concernées au navigateur Web.
DELETE
L’adresse email des paquets de données choisies a été copiée de la colonne email vers
email_registration
Les saisies sur une base de données peuvent être supprimées avec la commande
SQL DELETE. Vous pouvez utiliser cette dernière selon le schéma suivant :
DELETE FROM tableau WHERE colonne = wert
32
Si vous travaillez avec des IDs dans votre base de données, il faut s’identifier pour pouvoir
supprimer des données. Si vous souhaitez supprimer la saisie 5 de notre tableau exemple,
cela se fait comme ceci :
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "DELETE FROM users WHERE id = 5";
$affected = $pdo->exec($sql);
echo "$affected rows updated<br>";
?>
La commande SQL DELETE efface toujours une ligne entière d’une base de données. Pour
supprimer uniquement les valeurs spécifiées dans une colonne, il faut effectuer l’instruction
SQL correspondante. Avec UPDATE tableau SET colonne = NULL WHERE, vous pouvez
attribuer la valeur NULL à une colonne, à condition bien sûr que vous ayez permis la
valeur NULL pour cette colonne.
Prepared Statements
Avec PDO, vous pouvez mettre en œuvre des opérations de bases de données en tant
que Prepared Statements. Ces pré-instructions sont maintenant pratique courante dans le
développement Web et sont prises en charge par tous les systèmes de gestion de bases de
données modernes.
Dans les exemples précédents, nous avons entré les valeurs des paramètres directement
dans l’instruction SQL (SQL Statement). Les Prepared Statements au contraire fonctionnent
avec des espaces libres, qui vont être remplis avec des valeurs par la suite. Cela permet au
système de gestion de base de données de vérifier la validité des paramètres avant leur mise
en place. Les instructions préparées, à condition qu’elles soient mises en œuvre de manière
cohérente dans le code source, sont une protection efficace contre des injections SQL. Dans
ce modèle d’attaque, les cybercriminels créent ou modifient des commandes SQL afin
d’accéder à des données sensibles, écraser des données ou ajouter leurs propres
commandes au système.
Les injections SQL sont basées sur des failles de sécurité bien connues en relation avec les
bases de données SQL : si les saisies utilisateur sont effectuées avec des paramètres
statiques via $_GET par exemple, cela donne l’occasion aux cybercriminels d’enrichir leur
intrusion avec des métadonnées pouvant conduire à des effets indésirables si elles entrent
sans masquage dans le SQL-Interpreter. Ces intrusions peuvent être efficacement empêchées
avec des prepared Statements. Ces derniers agissent en tant que modèles pour les
commandes SQL transmises séparément des paramètres réels de la base de données. Ils
valident les données transférées, masquent les caractères méta automatiquement et
ajoutent des paramètres à la place des champs libres dans le Statement SQL.
Les Prepared Statements proposent l’avantage de la performance en dehors des aspects
relatifs à la sécurité. Cela se confirme lorsque la même commande SQL est exécutée en
33
boucle avec des paramètres différents. Une fois le Prepared Statement analysé, il est placé
dans le système de base de données et doit seulement y être exécuté avec de nouveaux
paramètres. Les requêtes les plus complexes peuvent ainsi être sensiblement accélérées.
Les Prepared Statements sont mis en place dans PDO à l’aide de la fonction prepare(). Ceci
prépare une déclaration pour l’exécution et renvoie un objet de ce statement. Le point
d’interrogation (?) ou bien un paramètre nommé par vous-même (Named Parameter) est
affiché pour caractériser les champs vides.
Prepared Statements avec des paramètres sans intitulé
L’exemple de code suivant affiche l’opération de base de données INSERT en tant que
Prepared Statement avec des paramètres sans intitulé :
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
// bind parameter
$statement ->bindParam(1, $forename);
$statement ->bindParam(2, $surname);
$statement ->bindParam(3, $email);
$statement ->bindParam(4, $password);
$forename = "Matti";
$surname = "Meikäläinen";
$email = "matti@meikäläinen.com";
$password = "jhgfd";
// display status
if ($statement->execute())
echo "New record $forename created successfully<br>";
?>
Nous créons tout d’abord un objet de Statement à l’aide de la fonction prepare() pour la
requête souhaitée et nous l’enregistrons dans la série $statement. Le point d’interrogation
apparaît au niveau de l’espace vide plutôt que des valeurs de paramètres concrètes.
34
Si le statement SQL ne comporte que des champs libres, les valeurs doivent être transmises
séparément dans le code ci-dessous. C’est là que la fonction PHP bindParam() entre en
scène. Nous utilisons l’opération « flèche » (->) pour accéder à la méthode de L’objet du
statement ainsi que pour lui attribuer des variables (1 correspond à la première question, 2 à
la deuxième, etc.).
Le template SQL ainsi créé peut maintenant être exécuté arbitrairement avec les paramètres
souhaités. Dans cet exemple, nous définissons des valeurs variables pour deux paquets de
données. L’exécution des pré-instructions SQL s’effectue via execute() pour chaque paquet de
données.
Les paramètres dotés d’intitulés ne doivent pas comporter d’espace ou de traits d’union (-).
Utilisez au lieu de cela des tirets bas (_).
L’exemple suivant montre l’opération de base de données INSERT comme une pré-instruction
avec des paramètres dotés d’intitulés :
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
// bind parameter
$statement ->bindParam(':forename', $forename);
$statement ->bindParam(':surname', $surname);
$statement ->bindParam(':email', $email);
$statement ->bindParam(':password', $password);
if ($statement->execute())
echo "New record $forename created successfully<br>";
$forename = "Matti";
35
$surname = "Meikäläinen";
$email = "matti@meikäläinen.com";
$password = "jhgfd";
$statement->execute();
// display status
if ($statement->execute())
echo "New record $forename created successfully<br>";
?>
Dans le Prepared Statement vous trouverez des paramètres avec intitulé tels
que :forename, :surname, :email et :password. Nous relions ces derniers aux
variables $forename, $surname, $email et $password via bindParam(). Dans cet exemple
nous avons nommé aussi bien les paramètres que les variables des noms de colonnes du
tableau correspondant. Cela n’est pas dicté par la syntaxe. Cependant, une appellation
cohérente et uniforme est recommandée pour des questions de lisibilité du code.
L’affectation des valeurs variables ainsi que l’exécution de l’instruction SQL se fait par
analogie de la même manière que l’exemple précédent.
Fonctions de date et d’heure dans MySQL
MySQL et MariaDB soutiennent diverses fonctions pour travailler avec les dates et heures. En
voici une liste complète. Nous nous limitons à une sélection dans notre tutoriel MySQL pour
débutants.
Fonctions de date et
heure Description
DAY() / DAYOFMONTH() Vous donne le jour et le mois (0-31) ; vous avez besoin d’une date ou
d’un Timestamp (horodatage) comme argument.
36
Fonctions de date et
heure Description
DATE() Extrait la date d’une indication de date ou d’heure ; exige une date ou
un horodatage comme argument.
TIME() Extrait l’heure d’une heure ou d’une date définie ; exige une date ou un
horodatage comme argument.
Un scénario d’application possible pour des fonctions de date et d’heure dans MySQL est par
exemple des requêtes de bases de données avec lesquelles tous les paquets de données qui
ont été créés un jour précis doivent être lus.
Le script suivant nous donne tous les paquets de données qui ont été créés dans notre
exemple de tableau :
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "SELECT forename, surname, email FROM users WHERE DATE(created_at) =
CURDATE()";
foreach ($pdo->query($sql) as $row) {
echo $row['forename'] . " " . $row['surname'] . "<br />";
echo "E-Mail: " . $row['email'] . "<br /><br />";
}
?>
Afin de limiter la sortie des éléments à ceux créés aujourd’hui, on utilise l’instruction SQL
suivante (condition) :
DATE(created_at) = CURDATE()
37
On extrait tout d’abord la date de la colonne où est placé l‘horodatage (created_at) à l’aide
de la fonction DATE(), puis on actualise cette date lors de l’étape suivante. La commande
SELECT sélectionne uniquement les entrées dont l’horodatage correspond à la date actuelle.
Sinon, il est aussi possible de sélectionner l’entrée qui a été mise à jour le 16/12/2016. Il faut
pour cela adapter la condition de notre SQL Statement :
SELECT forename, surname, email FROM users WHERE DATE(updated_at) = '2016-12-
16'
Dans ce cas, la date extraite de l‘horodatage est ajustée avec une date cible spécifique. De
plus, vous pouvez limiter des requêtes sur une année donnée, un mois, ou une journée
précise.
Le Statement suivant s’applique à toutes les entrées des utilisateurs du tableau qui ont été
ajoutés en décembre :
SELECT forename, surname, email FROM users WHERE month(created_at) = 12";
En dehors du signe égal (=), MySQL prend aussi en charge les opérations de conditions
suivantes :
= équivalent
!= différent
OR ou || ou
AND ou && et
38
L’instruction suivante sélectionne par exemple toutes les entrées qui ont été créées après
février et avant avril :
SELECT forename, surname, email FROM users WHERE MONTH(created_at) > 2 AND
MONTH(created_at) < 4";
Jusqu’ici, les informations de dates et heures sont stockées dans notre base de données au
format spécifié. Celles-ci ne sont pas déterminées avec MySQL et MariaDB. La
fonction DATE_FORMAT() vous donne la possibilité, de formater les dates et heures avec des
paramètres optionnels selon vos souhaits.
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "SELECT forename, surname, DATE_FORMAT(created_at,'%D %M %Y') AS
created_at FROM users WHERE id=1";
foreach ($pdo->query($sql) as $row) {
echo $row['forename'] . " " . $row['surname'] . " your profile was created at: " .
$row['created_at'] . ".<br /><br />";
}
?>
Le tableau suivant montre les paramètres possibles pour la fonction DATE_FORMAT() selon la
documentation MySQL.
Zone de
Paramètre Description valeurs/exemples
39
Zone de
Paramètre Description valeurs/exemples
40
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$statement = $pdo -> prepare("UPDATE user SET password = :password, updated_at
= NOW() WHERE id = 1");
$statement ->bindParam(':password', $password);
$password = "YXDli_89%s";
if ($statement ->execute()){
echo "Update successful";
} else {
echo "SQL Error <br />";
echo $statement->queryString."<br />";
echo $statement->errorInfo()[2];
}
?>
Si nous lançons le script via le serveur Web, nous recevons les informations suivantes :
SQL Error
UPDATE user SET password = :password, updated_at = NOW() WHERE id = 1
Table 'test.user' doesn't exist
La commande SQL UPDATE fait référence à un tableau portant le nom utilisateur (user). Nous
avons cependant nommé notre tableau exemple utilisateurs (users). Le serveur SQL ne peut
pas trouver le tableau demandé et fait apparaître le message Table 'test.user' doesn't exist.
La cause de cette erreur est donc seulement une faute de frappe dans le SQL statement, qui
peut être rapidement résolue.
La fonction errorinfo() renvoie des valeurs sous la forme d’une série composée de trois
éléments :
[0] = Code d’erreur SQL
[1] = Code d’erreur relatif au pilote
[2] = Message d’erreur relatif au pilote
Définissez via la saisie des éléments souhaités entre crochets quelles informations délivrer
via errorInfo().
41
Livraison d’un message d’erreur via le navigateur Web
Dans la pratique, les informations détaillées sur les erreurs sont rarement émises via le
navigateur Web. Les utilisateurs finaux peuvent généralement faire peu de choses avec ces
informations. Les cybercriminels potentiels cependant, utilisent parfois des messages
d’erreur pour suivre les requêtes SQL et identifier les points faibles d’une application. Il est
par conséquent recommandé d’informer les utilisateurs sur les cas d’erreurs et se stocker
leurs informations relatives à ces erreurs en interne. En pratique, cela donne ceci :
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$statement = $pdo->prepare("UPDATE user SET password = :password, updated_at =
NOW() WHERE id = 1");
$statement->bindParam(':password', $password);
$password = "YXDli_89%s";
if ($statement->execute()) {
echo "Update successful";
} else {
echo "Une erreur est malheureusement survenue lors de l’actualisation de votre mot
de passe. Veuillez contacter notre administrateur à l’adresse suivante :
[email protected].";
$error = DATE("Y-m-d H:i:s") . " - " . __FILE__ . " - " . $statement->queryString . " - " .
$statement->errorInfo()[2] . " \r\n";
file_put_contents("sqlerrors.log", $error, FILE_APPEND);
}
?>
Au lieu de la valeur renvoyée de la fonction errorinfo() par écho dans le navigateur Web,
nous stockons cette dernière avec l’horodatage actuel ainsi qu’avec le chemin vers le fichier
et le Statement SQL concerné dans la variable $error.
42
La fonction PHP DATE() indique l’horodatage Unix dans le format spécifié. La soi-disant
constante magique _FILE_ nous donne le chemin complet vers le fichier test.php. Le SQL
statement actuel est chargé comme dans l’exemple précédent via $statement->queryString.
Par la suite les données stockées dans $error à l’aide de la
fonction file_put_contents() comme texte du fichier sqlerrors.log dans le dossier htdocs.
Le tableau présente une sélection de nos chansons préférées des années 1960 et est destiné
à servir d’exemple négatif d’une mauvaise conception de base de données.
À première vue, notez que le tableau a de nombreux champs de données redondants. Nous
supprimons ces dernières en répartissant les données dans le cadre d’une normalisation
dans des tableaux séparés et reliés à l’aide de clés étrangères.
43
Formes normales
Une conception de base de données réussie se caractérise par un minimum de redondance.
La normalisation de tableaux de données permet d’éviter de dupliquer les entrées. Trois
formes normales se sont établies dans le cadre des modèles de bases de données
relationnelles pour que vous puissiez mettre en place des règles pour une structuration
optimale des données.
1. forme normale
Un tableau correspond à la première forme normale si toutes les valeurs d’attributs sont
atomiques. Les valeurs d’attributs sont considérées comme atomiques si elles ne
contiennent que des informations. Nous illustrons cela plus cela plus clairement avec un
exemple négatif.
Intéressons-nous par exemple les colonnes album_title et interpret du tableau album. Au lieu
d’exécuter chaque information contenue dans le tableau dans une colonne séparée, nous
avons inscrit les informations sur l’année de l’album entre parenthèses après le titre de
l’album ou déclaration de l’artiste. Cela ne s’utilise que lorsque nous voulons interroger tous
les titres par exemple, qui ont été publiés dans une année donnée.
Nous vous recommandons de créer des tableaux de données toujours selon les règles de la
première forme normale. Pour notre exemple, le tableau se présente de la manière suivante
:
Toutes les données sont maintenant séparées et donc facilement lisibles. Cependant, notre
tableau contient encore des redondances. Découvrez comment surmonter ces dernières
dans les prochaines étapes.
44
2. forme normale
Un tableau correspond à la deuxième forme normale lorsque toutes les conditions de la
première forme normale sont remplies et que chaque attribut non clé est pleinement
dépendant de l’ensemble de la clé primaire du tableau.
Les tableaux de données ne contiennent souvent qu’une seule colonne, faisant office de clé
primaire. Les tableaux de ce type sont automatiquement réglés sur la deuxième forme
normale, si les conditions de la première forme normale sont remplies. Il arrive cependant
parfois que la clé primaire d’un tableau découle de deux colonnes. C’est le cas dans notre
tableau exemple.
Pour charger le titre souhaité de la colonne titre du tableau, nous avons besoin
d’un album_id mais aussi du numéro de titre de la colonne track. Le titre Sympathy for the
Devil peut par exemple être chargé via la clé primaire album_ID = 3 et track = 1. Nous avons
donc affaire à une clé primaire composite. Ce dernier n’est cependant que nécessaire pour
les requêtes liées à la colonne title. Les colonnes album_title, released,
interpret et years_active sont exclusivement dépendantes d’album_id. Il n’y a donc pas de
dépendance fonctionnelle pour ces deux colonnes avec l’ensemble de la clé primaire. Les
conditions de la deuxième forme normale ne sont pas remplies.
Cela peut être modifié en stockant la colonne title dans un nouveau tableau et en la reliant à
une clé étrangère (album_id) avec le tableau de sortie.
45
Le tableau retravaillé album comporte seulement une clé primaire d’une seule pièce et
remplit donc automatiquement les conditions pour la deuxième forme normale. Le nouveau
tableau title ne comprend que le titre de la colonne non-clé. Ce dernier est dépendant
(fonctionnellement) des deux parties des clés primaires (album_id und track) et correspond
donc à la deuxième forme normale.
Mais des entrées redondantes sont présentes dans la deuxième forme normale de notre
tableau de données album.
3. forme normale
Un tableau de la troisième forme normale se conforme à toutes les conditions de la
deuxième forme normale, et donc aussi de la première forme normale. De plus, il ne doit pas
y avoir d’attribut non-clé en dépendance transitive. Cette condition peut sembler
compliquée, mais peut être expliquée en quelques mots : une dépendance transitive existe
toujours quand un attribut non-clé dépend d’un autre attribut non-clé. De plus, un attribut
non-clé ne doit pas être en dépendance transitive avec un attribut clé.
C’est exactement ce qui s’applique à notre tableau exemple album. Vous y trouverez les
colonnes interpret et years_active. Tandis que l’interprète peut être déterminé
par album_id, l’indication de l’année de la bande existante dépend transitivement
de album_id. Cela présente l’inconvénient que le système de gestion de base de données
stocke automatiquement une valeur redondante dans la colonne years_active à chaque fois
qu’un nouvel album d’un artiste est entré.
Afin de remplir les conditions de la troisième forme normale et ainsi retirer toutes les
redondances de notre tableau, nous devons aussi stocker la
colonne interpret incluant years_active dans un tableau séparé et le relier avec un tableau de
sortie album via une clé étrangère (interpret_id).
Nous obtenons ainsi trois tableaux normalisés : interpret, album et title.
46
Si nous voulons maintenant distribuer un titre précis incluant les informations de l’album
ainsi que de l’interprète, nous devons relier les trois tableaux séparés à l’aide de la
commande SQL JOIN et de la clé étrangère respective.
Définir une clé étrangère via phpMyAdmin
Dans la mesure où vous avez choisi InnoDB comme moteur de base de données, définissez
des relations de clés étrangères via l’interface graphique de votre programme
d’administration phpMyAdmin. La clé primaire d’un tableau peut ici être mise en œuvre
comme clé étrangère d’un certain nombre d’autres tableaux.
Dans notre exemple, nous avons besoin de deux connexions pour relier les trois tableaux
normalisés album, interpret et title :
• Nous utilisons comme première connexion la clé primaire album_id du
tableau album en tant que clé étrangère dans le tableau title.
• Nous utilisons pour la deuxième connexion la clé primaire interpret_id du
tableau interpret en tant que clé étrangère dans le tableau album.
Les relations des clés étrangères peuvent être illustrées par le graphique suivant :
47
Les tableaux normalisés album, title et interpret, reliés par des clés étrangères
Ceci vaut pour la liaison de tableaux de données : une colonne, qui agira comme une clé
étrangère, doit être fournie avec les attributs ou un index unique.
La relation entre clé primaire et clé étrangère correspond en général au type de relation 1:n.
Chaque champ de données dans la colonne de clé primaire du tableau A se trouve avec un
nombre quelconque (n) de champs de saisie dans la colonne de clé étrangère du tableau B.
Cependant, chaque champ de données dans la colonne de clé étrangère du tableau B se
réfère toujours à un seul champ de données dans la colonne de clé primaire du tableau A.
Nous avons par exemple quatre entrées dans la colonne de clé primaire album_id du
tableau, qui sont reliées via des clés étrangères title.album_id avec huit entrées du
tableau title.
48
Clé primaire et clé étrangère se trouvent dans une relation 1:n
Pour mettre en place les liens souhaités, nous avons placé les
tableaux album, interpret et title dans phpMyAdmin et nous avons défini nos clés primaires
dans le cadre de la création de tableau comme décrit dans l’option « Index ». Faites
également attention au fait que les colonnes qui font ensuite office de clés étrangères sont
également marquées via l’option Index en tant que INDEX ou UNIQUE. Seul INDEX s’avère
adapté pour les relations 1:n car les valeurs dans le champ UNIQUE ne doivent pas être
répétées par la suite.
Nous définissons lors de l’étape suivante la clé étrangère. Démontrons ceci avec l’exemple du
tableau album. Nous sélectionnons pour cela le tableau dans le panneau de navigation et
chargeons l’onglet structure depuis la barre de menu. C’est ici que se trouve le bouton
« Relation View » (aperçu des relations) :
49
Les relations de clés étrangères sont définies dans l’aperçu des relations d’un tableau de
données via le champ de saisie « Foreign key constraints » :
Les relations de clés étrangères sont définies dans le masque de saisie « Foreign key
contraints »
La colonne Interpret_id du tableau album doit faire office de clé étrangère, qui repose sur la
clé primaire interpret_id du tableau interpret.
Sous « Foreign key constraint (INNODB) «, vous définissez à quelles clés primaires les clés
étrangères font référence
Nous sélectionnons par conséquent le menu déroulant sous « Column » la
colonne interpret_id en tant que clé étrangère. Notez que seules les colonnes qui ont été
marquées comme INDEX, UNIQUE ou PRIMARY sont répertoriées. Dans le champ de saisie en
trois partie « Foreign key constraint (InnoDB) », nous choisissons quelle clé primaire de quel
tableau repose sur quelle base de données de notre clé étrangère. Nous avons fait les choix
suivants :
Base de données : test
Tableau : interpret
Clé primaire : interpret_id
Le champ « Constraint name » peut rester vide. Le système de gestion de base de données
attribue automatiquement un nom à cet endroit. Vous devez cependant définir, comment un
tableau avec une clé étrangère se comporte lorsque la clé étrangère sous-jacente à la clé
primaire est modifiée ou supprimée.
Si un artiste par exemple est supprimé du tableau-parent Interpret, la clé primaire également
associée disparait. Il s’agit ainsi de clarifier ce qu’il peut se produire avec les entrées qui se
rapportent à cette entrée via clé étrangère : les albums d’un artiste, dans notre exemple.
Pour déterminer le comportement d’un tableau avec une clé étrangère en cas
d’un UPDATE ou DELETE, quatre options sont à votre disposition sur MySQL ou MariaDB.
• RESTRICT: l’option RESTRICT comprend un changement dans le tableau-parent, dans
la mesure où d’autres tableaux existants y font référence. Dans notre cas, un paquet
50
de données dans le tableau interpret ne peut être supprimé, car les paquets de
données du tableau album y sont reliés.
• CASCADE : l’option CASCADE assure qu’un changement de tableau-parent sera
transmis dans tous les autres tableaux se référant à ce tableau-parent. Si nous
déplaçons par exemple l’interpret_id de The Rolling Stones de 2 à 8, ce changement
se reflète dans l’option Foreign-Key CASCADE, ainsi que dans tous les tableaux qui
utilisent interpret_id comme clé étrangère. Si une entrée dans un tableau-parent est
supprimée, cela signifie que tous les paquets de données reliés à cette entrée dans
d’autres tableaux seront supprimés. Attention : de cette façon, la suppression d’une
seule entrée peut entraîner la disparition de nombreux paquets de données.
• SET NULL : sélectionnez l’option SET NULL pour que la valeur dans la colonne de clé
étrangère soit placée sur NULL, dès que la clé primaire est modifiée ou supprimée
dans le tableau-parent.
• NO ACTION : l’option MySQL NO ACTION est équivalente à l’option RESTRICT.
Si vous avez défini l’option souhaitée pour la relation de clé étrangère, vous pouvez
confirmer la saisie en cliquant sur « enregistrer ». Le système de gestion de base de données
attribue automatiquement un nom pour la relation nouvellement créée.
Toutes les relations de clés étrangères définies sont répertoriées sous « Foreign key
constraints » dans l’onglet « Structure »
Types de JOIN-Typen dans MySQL et MariaDB
Les relations de clés étrangères vous permettent des données de différents tableaux
simultanément, et ce seulement à l’aide d’une instruction SQL. Vous avez pour cela quatre
types de JOIN à disposition sur MySQL et MariaDB :
• INNER JOIN : avec un INNER JOIN, le système de gestion de base de données cherche
des entrées communes dans les tableaux joints par JOIN. Seuls les paquets de
données comportant des matchs, disons, dans lesquels les valeurs correspondent aux
colonnes de liaison (clé primaire et clé étrangère) dans les deux tableaux.
• OUTER JOIN : avec un OUTER JOIN, on différencie des tableaux de gauche ainsi que
des tableaux de droite. A la différence d’un INNER JOIN, non seulement les paquets
de données comportant des similitudes dans les deux tableaux sont entrés, mais
aussi tous les paquets de données restants du tableau de droite ou de gauche.
51
• LEFT JOIN : tous les paquets de données du tableau de gauche sont entrés ainsi que
tous les paquets de données du tableau de droite dans lesquels se trouvent des
concordances.
• RIGHT JOIN : tous les paquets de données du tableau de droite sont entrés ainsi que
tous les paquets de données du tableau de gauche dans lesquels se trouvent des
concordances.
Nous nous limiterons à INNER JOIN dans le cadre de notre tutoriel MySQL pour débutants.
La syntaxe d’un INNER JOIN suit le schéma de base suivant :
SELECT * FROM tableau1
INNER JOIN tableau2 ON tableau1.cléétrangère = tableau2.cléprimaire
WHERE colonne = valeur
Le script exemple montre un INNER JOIN dans lequel le tableau album est relié au
tableau interpret. Nous lisons seulement les paquets de données avec lesquels il y a des
concordances entre clé primaire et clé étrangère.
album.interpret_id = interpret.interpret_id
Dans notre tableau de données, choisir entre LEFT et RIGHT JOIN n’entraînerait pas de
différence. Nous entrons alors les valeurs lues à l’aide d’une boucle foreach et la construction
de langue echo dans le navigateur.
52
L’exemple de script nous donne tous les albums stockés dans la base de données, incluant les
artistes et l’année de la première publication
Dans le cadre d’une instruction SQL, nous avons ainsi sélectionné l’indication de l’artiste du
tableau interpret et les données des titres des albums ainsi que la date de première
publication du tableau album.
La condition dans la clause WHERE permet de déterminer quels paquets de données
distribuer. Si nous voulons nous limiter aux albums publiés en 1968 seulement, nous
pouvons utiliser le script suivant :
<?php
1968";
?>
53
La condition WHERE released = 1968 limite les sorties à un album dans le navigateur. Beggars
Banquet des Rolling Stones est le seul album de notre base de données qui a été publié en
1968.
54
Reliez des tableaux de données selon vos souhaits avec la commande SQL JOIN
Les clauses WHERE peuvent ici aussi être définies selon le besoin avec une fonction de filtre :
si nous souhaitons uniquement récolter seulement les informations de la 7ème piste sur
l’album « Abbey Road » par exemple.
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$sql = "SELECT * FROM album
INNER JOIN interpret ON album.interpret_id = interpret.interpret_id
INNER JOIN title ON album.album_id = title.album_id WHERE track = 7 AND
album_title = 'Abbey Road'";
foreach ($pdo->query($sql) as $row) {
echo $row['title'] . " was released by " . $row['interpret'] . " as Track " . $row['track'] .
" on " . $row['album_title'] . " in " . $row['released'] . ".<br /><br />";
}
?>
55
INNER JOIN avec deux conditions analogiques AND
Notez que nous devons effectuer ceci avec une clé primaire en plusieurs parties sur le
tableau title. Si nous voulons faire référence à un titre particulier, nous avons besoins, en
dehors du numéro de piste, de l’album_id, qui est stocké avec le titre de l’album dans le
tableau album.
56