Qt pour les Bases De Données
Présentation générale
L’accès à une BDD dans Qt se fait via le module Qt SQL, qui permet de se connecter à différents SGBD (SQLite, MySQL, PostgreSQL…) et de les exploiter à travers l'API (ensemble de classes/méthodes C++) qu’il propose.
L’API du module SQL repose sur des drivers pour offrir une interface unifiée aux différents SGBDs.
Exploitation d’une BDD depuis Qt
Ci-dessous figurent un résumé des étapes à suivres pour exploiter une BDD.
Inclusion du module SQL de Qt
Pour utiliser les fonctionnalités SQL, il faut inclure le module dans le projet Qt :
-
Dans le fichier
.pro:[...] QT += sql [...] -
Dans le code C++ :
[...] #include <QtSql> [...]
Installation du driver SQL
Qt propose plusieurs drivers. Les plus courants sont :
-
SQLite : simple, aucun serveur requis.
-
MySQL : plus de fonctionnalités (accès concurrents, multi-utilisateurs, procédures stockées, réplication…).
Requiert l’installation du serveur MySQL.
Installation (exemple sous Qt5 Linux) :
-
Pour SQLite :
sudo apt install sqlite3 (1) sudo apt install libqt5sql5-sqlite (2)1 Installation de l’interface en ligne de commande + librairie SQLite 2 Installation du driver Qt SQLite (souvent installé par défaut) -
Pour MySQL : installer le package
libqt5sql5-mysql.sudo apt install mysql-server (1) sudo apt install libqt5sql5-mysql (2)1 Installation du serveur MySQL 2 Installation du driver Qt MySQL
|
Les drivers (→ |
Connexion à la base de données
-
Exemple SQLite (BDD locale, pas de mot de passe) :
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName("donnees.db"); // chemin du fichier local if(!db.open()) { qDebug() << "Erreur SQLite:" << db.lastError().text(); } -
Exemple MySQL (BDD distante, avec login/mot de passe) :
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); db.setHostName("adresse_serveur"); // ex: "192.168.1.10" db.setPort(3306); // port par défaut db.setDatabaseName("nom_base"); db.setUserName("utilisateur"); db.setPassword("votre_mot_de_passe"); if(!db.open()) { qDebug() << "Erreur MySQL:" << db.lastError().text(); }Pour se connecter à distance, le serveur MySQL doit autoriser les connexions distantes et l’utilisateur doit avoir les droits adaptés.
Élaboration et exécution de requêtes SQL
Le code est identique pour SQLite et MySQL.
-
Requête SQL simple :
QSqlQuery query; if (query.exec("SELECT * FROM clients")) { // traitement plus loin } else { qDebug() << query.lastError().text(); } -
Requête préparée (prévention des injections SQL) :
QSqlQuery query; query.prepare("SELECT * FROM clients WHERE nom = :nom"); query.bindValue(":nom", "Dupont"); if (query.exec()) { // traitement plus loin } else { qDebug() << query.lastError().text(); }
Exploitation du résultat d’une requête SQL
Le résultat d’exécution d’une requête SQL se nomme un resulset.
On accède aux enregistrements de ce resulset via un curseur.
Le code est identique pour SQLite et MySQL.
while(query.next()) {
int id = query.value(0).toInt();
QString nom = query.value("nom").toString();
// ...
}
Exemple complet
Ce programme propose une connexion à SQLite ou MySQL selon vos besoins.
#include <QCoreApplication>
#include <QtSql>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
// === CHOISIR LE MODE DE BASE ===
bool utiliserMySQL = false; // Mettre à true pour tester MySQL
QSqlDatabase db;
if(utiliserMySQL) {
db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("adresse_serveur"); // à adapter
db.setPort(3306);
db.setDatabaseName("nom_base");
db.setUserName("utilisateur");
db.setPassword("motdepasse");
} else {
db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("donnees.db");
}
if(!db.open()) {
qDebug() << "Erreur d'ouverture:" << db.lastError().text();
return 1;
}
// === REQUÊTE SIMPLE ===
QSqlQuery query;
if(query.exec("SELECT id, nom FROM clients")) {
while(query.next()) {
int id = query.value("id").toInt();
QString nom = query.value("nom").toString();
qDebug() << "ID:" << id << "Nom:" << nom;
}
} else {
qDebug() << "Erreur (requête simple):" << query.lastError().text();
}
// === REQUÊTE PRÉPARÉE ===
query.prepare("SELECT * FROM clients WHERE nom = :nom");
query.bindValue(":nom", "Dupont");
if(query.exec()) {
while(query.next()) {
qDebug() << "Résultat préparée:" << query.value("nom").toString();
}
} else {
qDebug() << "Erreur (requête préparée):" << query.lastError().text();
}
db.close();
return 0;
}
Points clés
-
Adapter le nom du driver selon le type de base.
-
Pour MySQL vérifier le port, le hostname, le login/mot de passe.
-
Toujours vérifier le retour de
lastError()en cas d’échec. -
Les requêtes préparées sont indispensables pour la sécurité.
Ressources
-
Activité : Base de données
Une activité Qt + Bdd réalisé par un éminent confrère.
Annexes
Configuration de MySQL
-
Configurer mot de passe root
$ sudo mysql mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'mysqladmin'; Query OK, 0 rows affected (0,02 sec) mysql> FLUSH PRIVILEGES; Query OK, 0 rows affected (0,01 sec) mysql> SELECT user, plugin FROM mysql.user; +------------------+-----------------------+ | user | plugin | +------------------+-----------------------+ | debian-sys-maint | caching_sha2_password | | mysql.infoschema | caching_sha2_password | | mysql.session | caching_sha2_password | | mysql.sys | caching_sha2_password | | root | mysql_native_password | +------------------+-----------------------+ 5 rows in set (0,00 sec) mysql> exit -
Créer un nouvel utilisateur MySQL :
$ mysql -u root -p mysql> SHOW VARIABLES LIKE 'validate_password%'; (1) +-------------------------------------------------+--------+ | Variable_name | Value | +-------------------------------------------------+--------+ | validate_password.changed_characters_percentage | 0 | | validate_password.check_user_name | ON | | validate_password.dictionary_file | | | validate_password.length | 8 | | validate_password.mixed_case_count | 1 | | validate_password.number_count | 1 | | validate_password.policy | MEDIUM | | validate_password.special_char_count | 1 | +-------------------------------------------------+--------+ 8 rows in set (0,01 sec) mysql> CREATE USER 'ragnar'@'%' IDENTIFIED WITH mysql_native_password BY 'V@lh@ll@4m3!'; (2) Query OK, 0 rows affected (0,01 sec) mysql> exit Bye1 Affichage politique de mot de passe ⇒ 8+ caractères ET majuscules/minuscules ET chiffres ET caractères spéciaux 2 Cration utilisateur “ragnar” avec mot de passe en accord avec la politique de sécurité (→ “V@lh@ll@4m3!”) -
Créer une BDD accessible à l’utilisateur nouvellement créé :
$ mysql -u root -p mysql> CREATE DATABASE dbvikings; (1) Query OK, 1 row affected (0,03 sec) mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, DROP, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES ON dbvikings.* TO 'ragnar'@'%'; (2) Query OK, 0 rows affected (0,01 sec) mysql>1 Création BDD 2 Attribution des droits SELECT, UPDATE … à l’utilisateur “ragnar” connecté depuis n’importe quelle IP (→ '%') -
Autoriser un accès distant à MySQL en modifiant
/etc/mysql/mysql.conf.d/mysql.cnf:# If MySQL is running as a replication slave, this should be # changed. Ref https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_tmpdir # tmpdir = /tmp # # Instead of skip-networking the default is now to listen only on # localhost which is more compatible and is not less secure. bind-address = #192.168.5.12(1) mysqlx-bind-address = 127.0.0.11 Mettre IP de la VM LUbuntu ou de la Raspberry Pi -
Redémarrer le service avec :
sudo systemctl restart mysql.service
-
Autoriser l’accès à MySQL dans le firewall :
$ sudo ufw allow mysql La règle a été ajoutée La règle a été ajoutée (v6)
🕮 Liens :
🞄 🞄 🞄