Ludovic ROLAND

Blog technique sur mes expériences de développeur.

Interagir avec une base de données en Perl 5 grâce au module DBI (7/7) : Les placeholders

7 août 2022

Comme je le disais, c’est le chapitre le plus compliqué de cette partie du tutoriel.

Accrochez - vous, la fin du tutoriel est proche ! ;)

Plan

Définition

Derrière ce mot barbare se cache en réalité la notion de requêtes “préparées”.

Les placeholders s’utilisent généralement dans 2 cas.

Cas n°1

Ce système de requête étant beaucoup plus rapide pour votre base de données, les placeholders seront privilégiés pour des requêtes exécutées plusieurs fois au cours de votre programme.

Cas n°2

Ce système est également privilégié lorsque vos requêtes sont exécutées en fonction de variables. En effet, ce système permet alors de sécuriser vos requêtes, et notamment de protéger efficacement vos programmes contre les injections SQL.

Écrire un placeholder

Actuellement…

Considérons par exemple les 2 requêtes suivantes :

INSERT INTO MARQUE (nomMarque) VALUES ('Volvo');
INSERT INTO MARQUE (nomMarque) VALUES ('Skoda');

Ces 2 requêtes permettent d’ajouter dans la table MARQUE les marques Volvo et Skoda.

Avec vos connaissances actuelles, pour exécuter ces 2 requêtes, vous faites :

my $requete1 = 'INSERT INTO MARQUE (nomMarque) VALUES (\'Volvo\')';

my $prep = $dbd->do($requete1)
    or die 'Impossible d\'exécuter la requête : '.$dbd->errstr;

my $requete2 = 'INSERT INTO MARQUE (nomMarque) VALUES (\'Skoda\')';

$prep = $dbd->do($requete2)
    or die 'Impossible d\'exécuter la requête : '.$dbd->errstr;

Nous allons voir ensemble comment optimiser cette action via la mise en place d’un placeholder.

Écrire un placeholder

La mise en place d’un placeholder se découpe en 3 parties :

  • préparation de la requête ;
  • exécution de la requête ;
  • exploitation des résultats.

Préparation de la requête

C’est la première étape. Même si vous ne faites pas encore le parallèle, sachez que vous savez déjà préparer une requête. En effet, c’est ce que vous faites à chaque fois lors de vos requêtes de sélection, grâce à la fonction prepare du descripteur de base.

Pour utiliser un placeholder, vous devez donc préparer la requête. Contrairement aux requêtes de sélection, pour mettre en place un placeholder, la requête doit être écrite sans sa partie variable.

Je sais que ça peut paraître abstrait dit comme ça… En fait, la partie variable de la requête est remplacée par un marqueur. Ce marqueur est un point d’interrogation.

Voyons tout de suite ce que ça donne :

my $requete = 'INSERT INTO MARQUE (nomMarque) VALUES (?)';

my $prep = $dbd->prepare($requete)
    or die 'Impossible de préparer la requête : '.$dbd->errstr;

Exécution de la requête

À cette étape, la requête est prête à être exécutée. C’est d’ailleurs ce que nous allons faire, en appelant la fonction execute que vous utilisez déjà pour vos requêtes de sélection.

Mais vous vous doutez bien qu’il y a une petite nouveauté !

Afin de reconstituer la partie variable de votre requête, il faut transmettre à la fonction execute la liste de vos paramètres.

Ainsi, pour ajouter la marque “Volvo”, on fera :

$prep->execute('Volvo');

Il suffit de réitérer cette dernière ligne avec un autre argument pour exécuter l’autre requête d’insertion !

L’exploitation des résultats, quant à elle, ne change pas par rapport à ce que nous avons vu précédemment.

Pour résumer

Afin de résumer ce que nous avons vu jusqu’ici sur les placeholders, voici le code source complet pour les 2 requêtes d’insertion précédentes.

#!/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 = 'INSERT INTO MARQUE (nomMarque) VALUES (?)';

my $prep = $dbd->prepare($requete)
    or die 'Impossible de préparer la requête : '.$dbd->errstr;

$prep->execute('Volvo');
$prep->execute('Skoda');

$prep->finish;

$dbd->disconnect;

Avec des variables

Il est possible de réaliser les requêtes grâce à la concaténation, mais c’est TRÈS fortement déconseillé !

À la place, il est préférable d’utiliser les placeholders.

Par exemple, essayons de réaliser un script qui affiche l’identifiant dans la base de données d’un vendeur, dont le nom et le prénom sont renseignés par l’utilisateur.

#!/usr/bin/perl

use strict;
use DBI;

my $base    =   'Zvoitures';
my $hote    =   '127.0.0.1';
my $login   =   'root';
my $mdp     =   '';

print 'Saisir le prénom du vendeur : ';
my $prenom = <STDIN>;
chop($prenom);

print 'Saisir le nom du vendeur : ';
my $nom = <STDIN>;
chop($nom);

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 numVendeur FROM VENDEUR WHERE nomVendeur = ? AND prenomVendeur = ?';

my $prep = $dbd->prepare($requete)
    or die 'Impossible de préparer la requête : '.$dbd->errstr;

$prep->execute($nom, $prenom)
    or die 'Impossible d\'exécuter la requête : '.$prep->errstr;

my ($num) = $prep->fetchrow_array;

$prep->finish;

print 'Le numéro du vendeur dans la base de données est : '.$num;

$dbd->disconnect;

En exécutant le script, vous devriez alors avoir l’affichage suivant :

> perl script_vendeur.pl
Saisir le prénom du vendeur : Batte
Saisir le nom du vendeur : MANE
Le numéro du vendeur dans la base de données est : 2

Bien que ce type de requêtes soit sécurisé, il est fortement conseillé d’ajouter une vérification des données saisies par l’utilisateur à l’aide par exemple d’expressions rationnelles !

Voilà, la partie sur le module DBI est maintenant terminée. J’espère que cette partie du tutoriel vous aura servi et surtout plu ! ;)

Commentaires