Blog technique sur mes expériences de développeur.
6 août 2022
Nous allons voir par la suite qu’il n’existe pas qu’une seule façon d’exécuter des requêtes en Perl.
Puisqu’il faut bien choisir, je vous propose de commencer par les requêtes de sélection.
Pas de panique, les autres types de requêtes seront vus dans les chapitres qui suivent. ;)
Ce cours était originalement publié sur la plateforme OpenClassrooms. La plateforme OpenClassrooms ayant supprimée ce tutoriel en 2020 et le tutoriel étant sous licence CC BY-SA 4.0, je vous propose de le (re)découvrir ici.
Prenons un exemple. Je vous propose de travailler sur la requête suivante :
SELECT * FROM MARQUE
Avant d’exécuter la requête, nous devons la préparer. Pour ça, nous allons utiliser la fonction prepare()
de notre descripteur de base en lui précisant notre requête en tant que paramètre.
Pour préparer les requêtes, on retrouve généralement 2 types de syntaxe. Soit en un étape, soit en 2 étapes. Voici tout de suite un exemple :
#Syntaxe en 1 ligne
my $prep = $dbd->prepare('SELECT * FROM MARQUE');
#Syntaxe en 2 lignes
my $requete = 'SELECT * FROM MARQUE';
my $prep = $dbd->prepare($requete);
Ici, je viens donc de préparer la requête me permettant de sélectionner tous les champs de la table MARQUE
de notre base de données.
Jusqu’ici, il n’y a rien de bien compliqué, cependant, il ne faut pas confondre les notions de préparation de d’exécution. Ici, nous préparons notre requête à être exécuter, mais nous ne pouvons en aucun cas en extraire un quelconque résultat.
Vous pouvez constater l’apparition d’une nouvelle variable : $prep
. C’est cette variable que l’on utilisera dans la suite de notre programme pour exécuter notre requête et en exploiter les résultats.
Sachez également qu’il est une nouvelle fois possible de gérer d’éventuelles exceptions grâce aux mots-clefs or die
.
Voici d’ailleurs un exemple de syntaxe :
my $requete = 'SELECT * FROM MARQUE';
my $prep = $dbd->prepare($requete)
or die 'Impossible de préparer la requête : '.$dbd->errstr;
Le fait de concaténer notre message d’erreur à la valeur retourner par la méthode errstr
de notre descripteur de base nous permet de connaître avec précision l’origine du dysfonctionnement.
Maintenant que notre requête est préparée, nous allons pouvoir passer à son exécution. Pour ça, nous allons utiliser la méthode execute
à partir de la variable qui contient notre requête préparée.
Puisqu’un exemple est souvent plus parlant, je vous propose un :
$prep->execute;
Comme à chaque fois, il est possible de gérer les éventuelles exceptions :
$prep->execute
or die 'Impossible d\'exécuter la requête : '.$prep->errstr;
Sans forcément rentrer dans les détails, il faut que vous sachiez qu’une exécution de requête prend de la place dans la mémoire de votre ordinateur. Il est donc nécessaire, lorsqu’on ne souhaite plus utiliser les résultats de la requête, de libérer cette mémoire réservée.
Pour ça, nous allons utiliser la fonction finish
.
Voici comment procéder :
$prep->finish;
Afin de résumer ce que nous venons de voir au cours de ce chapitre, je propose de voir le code complet :
#!/usr/bin/perl
use strict;
use DBI;
my $base = 'Zvoitures';
my $hote = '127.0.0.1';
my $login = 'root';
my $mdp = '';
my $dbd = DBI->connect( "dbi:mysql:dbname=$base;host=$hote;",$login, $mdp)
or die 'Connexion impossible à la base de données : '.DBI::errstr;
my $requete = 'SELECT * FROM MARQUE';
my $prep = $dbd->prepare($requete)
or die 'Impossible de préparer la requête : '.$dbd->errstr;
$prep->execute
or die 'Impossible d\'exécuter la requête : '.$prep->errstr;
$prep->finish;
$dbd->disconnect;
Oui mais moi, je n’aime pas écrire mes requêtes en ligne, j’aime bien faire des blocs. Ce n’est pas possible ?
N’oubliez jamais que vous utilisez Perl, et qu’il est toujours possible d’utiliser des marqueurs. Ainsi, il est tout à fait possible d’écrire vos requêtes sous la forme d’un bloc comme il est de convention d’écriture dans la plupart des SGBD :
my $requete = <<"SQL";
SELECT *
FROM MARQUE
SQL
Cette écriture sera d’autant plus lisible lorsque vous aurez besoin d’écrire de grosses requêtes avec tout un tas de jointures.
Maintenant que nous venons de voir comment faire une requête, je vous propose de voir comment exploiter les résultats renvoyés.
Exploiter les résultats Nous allons voir ici 2 cas, ce qui nous permettra de rencontrer et manipuler différentes fonctions.
Reprenons la requête précédente :
SELECT * FROM MARQUE
Puisque nous connaissons la structure de notre table de données, nous pouvons transformer notre requête afin d’en détailler les différents champs que nous voulons sélectionner.
Voici ce que ça donne :
SELECT numMarque, nomMarque FROM MARQUE
Si vous n’êtes pas convaincus que ces 2 requêtes sont équivalentes, je vous invite à les exécuter dans votre SGBD. ;)
Il existe une multitude de manières d’exploiter les données renvoyées par une requête SQL. Je vous propose de voir la méthode la plus courante.
Puisque bien souvent un bout de code vaut mieux que de longues explications, voici tout de suite comment faire :
while (my($numMarque, $nomMarque) = $prep->fetchrow_array ) {
print $numMarque . '. ' . $nomMarque . "\n";
}
Quelques explications : La méthode execute
renvoie un tableau qui contient toutes les lignes qui ont été sélectionnées par notre requête. La méthode fetchrow_array
est une fonction qui renvoie une ligne de ce fameux tableau. C’est d’ailleurs parce que cette fonction nous renvoie un tableau que nous pouvons utiliser une liste pour recueillir nos résultats.
La boucle while
quant à elle, nous permet de réaliser une boucle sur les lignes du tableau contenant les résultats et ainsi, d’exploiter toutes les lignes et donc tous les résultats sans en oublier.
Si l’on reprend le script précédent, ces 3 lignes se placent juste avant l’instruction $prep->finish
.
Voici tout de suite l’affichage produit par ce script :
> perl requete.pl
1. ZeroMobile
2. Renault
3. Peugeot
4. Ferrari
5. Porsche
6. Fiat
7. Ford
8. Tata Motor
9. Smart
10. Citroen
Pour rappel, il s’agit du cas où nous ne connaissons pas le nombre d’arguments.
Reprenons donc notre requête sous sa première forme :
SELECT * FROM MARQUE
Dans ce second cas, utiliser une liste pour recueillir les résultats n’a pas de sens, puisque nous ne connaissons pas le nombre de champs renvoyés. Il conviendra alors d’utiliser un tableau.
Bien sûr, l’exploitation sera différente du premier cas. Afin d’afficher les résultats, nous allons être obligés d’utiliser une nouvelle boucle : la boucle foreach
. Nous allons donc imbriquer 2 boucles afin d’exploiter les résultats de notre requête.
Voyons tout de suite comment faire :
while (my @data = $prep->fetchrow_array ) {
foreach my $elt (@data) {
print $elt.' ';
}
print "\n";
}
En exécutant ce script dans votre terminal, vous devriez alors avoir :
> perl requete.pl
1 ZeroMobile
2 Renault
3 Peugeot
4 Ferrari
5 Porsche
6 Fiat
7 Ford
8 Tata Motor
9 Smart
10 Citroen
Cette méthode peut se révéler intéressante dans le cas d’une requête SQL ayant énormément de champs dans le SELECT
afin de rendre le code de votre script plus clair.
Avez-vous une idée sur le moyen d’obtenir le nombre de lignes renvoyées par votre requête SQL ?
Vous avez 10 minutes pour y réfléchir ! :p
Tic… Tac… Tic… Tac…
Voyons ensemble les 3 réponses qui reviennent le plus souvent.
while
.COUNT(*)
.L’idée du compteur à incrémenter dans la boucle while
n’est pas une mauvaise idée, mais la bonne réponse est bien évidemment la dernière !
En effet, il existe une fonction qui permet de connaître le nombre de lignes retournées par notre requête. La voici sans plus attendre :
$prep->rows
Ainsi, si on ajoute cette ligne à notre script :
print 'Il existe '.$prep->rows.' marques de voitures.';
Nous allons obtenir à l’écran :
Il existe 10 marques de voitures.
Comme à chaque fois en fin de chapitre, voici le script complet de ce que nous avons vu :
#!/usr/bin/perl
use strict;
use DBI;
my $base = 'Zvoitures';
my $hote = '127.0.0.1';
my $login = 'root';
my $mdp = '';
my $dbd = DBI->connect("dbi:mysql:dbname=$base;host=$hote;",$login, $mdp)
or die 'Connexion impossible à la base de données : '.DBI::errstr;
my $requete = 'SELECT * FROM MARQUE';
my $prep = $dbd->prepare($requete)
or die 'Impossible de préparer la requête : '.$dbd->errstr;
$prep->execute
or die 'Impossible d\'exécuter la requête : '.$prep->errstr;
while (my($numMarque, $nomMarque) = $prep->fetchrow_array ) {
print $numMarque.'. '.$nomMarque."\n";
}
print 'Il existe '.$prep->rows.' marques de voitures.';
$prep->finish;
$dbd->disconnect;
Vous avez acquis un certain nombre de connaissances, c’est pourquoi je vous propose d’ores et déjà un petit TP !