Vous êtes sur la page 1sur 8

INTRODUCTION A L’EXPLOITATION DES

BASES DE DONNEES AVEC C++ SOUS QT

1. Introduction

Prérequis :

 avoir des bases en C++ ;


 connaître le framework Qt ;
 savoir utiliser un SGBD ;
 avoir des bases en SQL.

Pour réaliser des applications avec Bases de données, on doit utiliser le module
QtSql. Le module QtSql fournit une interface de gestion indépendante de Bases
de Données relationnelles. Cette interface est soutenue par un ensemble de
classes utilisant l’architecture MVC (Modèle-Vue-Controleur) qui assurent une
bonne convivialité pour l’interface utilisateur.

Avant toute chose il faut modifier le fichier .pro pour que les classes d'accès
aux données soient accessibles. Pour ce faire il suffit d'ajouter la ligne suivante
au fichier .pro :
QT+=sql

2. Les pilotes disponibles

Pour se connecter à une base de données, on aura besoin d’un pilote


(driver).
Différents pilotes sont utilisables au niveau de la connexion, en fonction du
SGBD.
Qt supporte la plupart des SGBD disponibles aujourd’hui (Oracle, MySQL,
SQLite, Microsoft Sql Server, etc.)

Une liste de SGBD et leur pilote supporté par Qt


Pilote Base de données

QDB2 IBM DB2 version 7.1 et ultérieure

QIBASE Borland InterBase

QMYSQL MySQL

QOCI Oracle (Oracle Call Interface)

ODBC (Microsoft SQL Server,


QODBC
Microsoft Access)

QPSQL PostgreSQL versions 6.x et 7.x

QSQLITE SQLite version 3 et ultérieure

QSQLITE2 SQLite version 2

QTDS Sybase Adaptive Server

3. Connexion à la Base de données

Quelques méthodes nécessaires pour la connexion :

 Ajout du pilote : la méthode addDatabase()

Pour ce faire, on va créer un objet de la classe QSqlDatabase.


Comme valeur, on va lui assigner le retour de la méthode statique
addDatabase() qui reçoit en paramètre sous forme de chaîne de caractères le
nom du pilote :

En exemple, pour une base de données MySQL, nous prendrons la valeur


QMYSQL.
Il faudra alors ajouter au code la ligne :
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");

 Précision de l’hôte : la méthode setHostName()


 Précision du nom d'utilisateur : la méthode setUserName()
 Précision du mot de passe : la méthode setPassword()
 Précision de la base de données que l'on utilisera : setDatabaseName()

Chacune de ces méthodes prend un QString renseignant l'information que l'on


modifie.
Pour continuer, il faut utiliser la méthode open(), qui ouvre la connexion, et
renvoie un booléen : true si la connexion a réussi, false si elle a échoué.

Pour fermer la base de données, on utilisera la méthode close().

Exemple : MySQL

QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setDatabaseName("toto");
db.setUserName("root");
db.setHostName("localhost");
db.setPassword("");
if(db.open())
qDebug() << "Ouverture de la base de données avec succès";
else qDebug() << "Echec d'ouverture de la base de données";

4. Exécution d’une requête


Une requête est représentée par la classe QSqlQuery.

QSqlQuery fournit un moyen d'exécuter et de manipuler les requêtes SQL.


Cette classe encapsule les fonctionnalités impliquées dans la création, la
navigation et la récupération de données à partir de requêtes SQL qui sont
exécutées sur un QSqlDatabase. Elle peut être utilisée pour exécuter le langage
de manipulation de données (DML) telles que SELECT, INSERT, UPDATE et
DELETE ainsi que le langage de définition de données (DDL) telles que CREATE
TABLE.

Procédure :

On crée un objet QSqlQuery, et pour exécuter une requête, on utilise la


méthode exec(), en lui passant la requête en paramètre.
La méthode exec() retourne un booléen : true si la requête a réussi, false
si elle a échoué.

Exemple : une requête récupérant le montant des TVA possible dans la table
tva :
QSqlQuery query("SELECT montant_tva FROM tva;");
if(query.exec())
qDebug() << "Ouverture de la base de données avec succès";
else qDebug() << "Echec d'ouverture de la base de
données";

5. Traitement du résultat de la requête

4.1. Accès aux enregistrements

La classe QSqlQuery fournit différentes méthodes pour naviguer à travers les


résultats de la requête:

 next(): la fonction next() permet d’avancer d’une ligne de résultat et de


récupérer cette dernière. Après l’exécution de la méthode exec(), un
premier appel de next() avance le curseur sur le premier enregistrement
ou sur la première ligne de résultat, ensuite un appel récursif permet de
parcourir toutes les lignes de résultats. Ceci se fait généralement dans
une boucle.
while ( query.next() )
{
//manipuler vos enregistrements ici
}

next() renvoie toujours TRUE tant qu’il reste de lignes à parcourir, on


sort de la boucle lorsqu’elle renvoie FALSE(dernier enregistrement).

 first(): récupère le premier enregistrement dans le résultat.

 last(): récupère le dernier enregistrement dans le résultat.

 previous(): récupère l’enregistrement qui précède la ligne courante de


résultat

 at() : retourne l’index ou la position de ligne courante .


 La fonction value() permet de récupérer la valeur positionnée en fonction de
l'entier passé en paramètre de cette fonction. Les champs sont numérotés de
gauche à droite lors de l'utilisation de SELECT, plusieurs valeurs peuvent être
retournées.

4.2. Accès aux champs d’un enregistrement

Durant le parcours des enregistrements, on peut avoir accès aux champs d’un
enregistrement en faisant :

query.value( index ).toInt(), ou

query.value( index ).toString(), ou

query.value( index ).toDouble(), ou

query.value( index ).toFloat() , etc.

selon le type de donnée du champ


index est de type entier et représente la position du champ dans la ligne de
résultat. Si l’on exécute une requête de genre ‘ SELECT nom,prenom FROM
etudiant’, le champ ‘nom’ correspond à l’index 0, ‘prenom’ correspond à 1 et
ainsi de suite car les champs sont numérotés à partir de 0.

toX(): fait un transtypage en un type de donnée X qui peut être un


(int,QString,double,float,..etc), car la méthode query.value( index ) renvoie
un objet de type QVariant qui est une union de la plupart des types de
données en Qt.

Exemple
while (query.next() )
{
//on recupere title sous forme de QString
QString title = query.value(0).toString();
//on récupère year sous forme d’entier
int year = query.value(1).toInt();
// traitement des valeurs
………………………………
}

On peut également accéder aux valeurs de champs en utilisant le nom des


colonnes de la table.

On peut convertir un nom de champ en son index avec la


méthode record().indexOf() .

Exemple

QSqlQuery query("SELECT * FROM artist");


int titleIndex = query.record().indexOf("title");
while ( query.next() )
{
Qstring title = query.value(titleIndex).toString();
//……………
}
6. Variables bind et requêtes préparées

5.1. Qu'est-ce qu'une variable bind?

Une variable bind est une variable comme une autre mis à part qu'elle est
présente directement dans la requête SQL et qu’on va lui associer une variable
applicative.

Quelques motivations pour les variables bind :

 Raisons de lisibilité
 Raisons d'optimisation
 Raisons de sécurité : éviter les attaques de type « injections SQL »

5.2. Requêtes préparées

Une requête préparée est une requête comme une autre, sauf qu'au lieu de
mettre directement les valeurs, on va mettre des marqueurs (? ou un marqueur
nominatif), et les remplacer plus tard. Ainsi, la requête sera réutilisable pour
différentes valeurs.
Pour en créer une, on utilise toujours l'objet QSqlQuery. La fonction QSqlQuery
::prepare() prédispose la requête SQL à l'exécution, elle permet de construire des
requêtes contenant des éléments variables. Cette fonction renvoie un booléen pour
confirmer ou non la préparation de la requête.

Pour remplacer un marqueur, il y a deux possibilités :


 Cas d’un marqueur nominatif : on va utiliser la méthode

QSqlQuery::bindValue en mettant le nom du marqueur puis la valeur ;


 Cas d’un point d'interrogation : on utilisera QSqlQuery::addBindValue()
en passant la valeur : il faudra l'utiliser dans l'ordre des ?

Exemple :
QSqlQuery q;
//Marqueurs ?
q.prepare("UPDATE matable SET monchamp1=?, monchamp2=?");
q.addBindValue("Coucou");
q.addBindValue(42);

//Marqueurs nominatifs
q.prepare("UPDATE matable SET monchamp1=:premierevaleur,
monchamp2=:deuxiemevaleur");
q.bindValue(":premierevaleur", "Coucou");
q.bindValue(":deuxiemevaleur", 42);

Remarque : les marqueurs nominatifs commencent par le caractère : (Doubles-


points).