Exécution d'instructions SQL
La classe ` QSqlQuery ` fournit une interface permettant d'exécuter des instructions SQL et de parcourir le jeu de résultats d'une requête.
Les classes ` QSqlQueryModel ` et ` QSqlTableModel `, décrites dans la section suivante, offrent une interface de plus haut niveau pour accéder aux bases de données. Si vous n’êtes pas familier avec le langage SQL, vous pouvez passer directement à la section suivante (Utilisation des classes du modèle SQL).
Exécution d'une requête
Pour exécuter une instruction SQL, il suffit de créer un objet QSqlQuery et d'appeler la méthode QSqlQuery::exec() comme suit :
QSqlQuery query;
query.exec("SELECT name, salary FROM employee WHERE salary > 50000");Le constructeur QSqlQuery accepte un objet QSqlDatabase facultatif qui spécifie la connexion à la base de données à utiliser. Dans l'exemple ci-dessus, nous ne spécifions aucune connexion ; la connexion par défaut est donc utilisée.
En cas d’erreur, la méthode ` exec()` renvoie ` false`. L’erreur est alors accessible via ` QSqlQuery::lastError()`.
Parcourir le jeu de résultats
QSqlQuery permet d’accéder au jeu de résultats enregistré par enregistrement. Après l’appel à exec(), le pointeur interne de QSqlQuery se trouve à une position avant le premier enregistrement. Il faut appeler une fois la fonction ` QSqlQuery::next()` pour passer au premier enregistrement, puis appeler à plusieurs reprises la fonction ` next()` pour accéder aux autres enregistrements, jusqu’à ce qu’elle renvoie ` false`. Voici une boucle type qui parcourt tous les enregistrements dans l’ordre :
while (query.next()) {
QString name = query.value(0).toString();
int salary = query.value(1).toInt();
qDebug() << name << salary;
}La fonction QSqlQuery::value() renvoie la valeur d’un champ dans l’enregistrement courant. Les champs sont spécifiés sous forme d’index commençant à zéro. La fonction ` QSqlQuery::value()` renvoie un objet de type ` QVariant`, capable de contenir divers types de données C++ et Qt de base, tels que ` int`, ` QString` et ` QByteArray`. Les différents types de base de données sont automatiquement mappés vers leur équivalent Qt le plus proche. Dans l’extrait de code, nous appelons les fonctions ` QVariant::toString()` et ` QVariant::toInt()` pour convertir les `variants` en ` QString ` et ` int`.
Pour un aperçu des types recommandés à utiliser avec les bases de données prises en charge par Qt, veuillez vous reporter à ce tableau.
Vous pouvez naviguer au sein du jeu de données à l’aide des fonctions QSqlQuery::next(), QSqlQuery::previous(), QSqlQuery::first(), QSqlQuery::last() et QSqlQuery::seek(). L’index de la ligne actuelle est renvoyé par QSqlQuery::at(), et le nombre total de lignes dans le jeu de résultats est disponible via QSqlQuery::size() pour les bases de données qui le prennent en charge.
Pour déterminer si un pilote de base de données prend en charge une fonctionnalité donnée, utilisez la fonction QSqlDriver::hasFeature(). Dans l’exemple suivant, nous appelons la fonction QSqlQuery::size() pour déterminer la taille d’un jeu de résultats de la base de données sous-jacente si celle-ci prend en charge cette fonctionnalité ; dans le cas contraire, nous naviguons jusqu’au dernier enregistrement et utilisons la position de la requête pour connaître le nombre d’enregistrements.
QSqlQuery query;
int numRows;
query.exec("SELECT name, salary FROM employee WHERE salary > 50000");
QSqlDatabase defaultDB = QSqlDatabase::database();
if (defaultDB.driver()->hasFeature(QSqlDriver::QuerySize)) {
numRows = query.size();
} else {
// this can be very slow
query.last();
numRows = query.at() + 1;
}Si vous naviguez au sein d’un jeu de résultats et que vous utilisez next() et seek() uniquement pour parcourir vers l’avant, vous pouvez appeler QSqlQuery::setForwardOnly() avant d’appeler exec(). Il s’agit d’une optimisation simple qui accélérera considérablement la requête lorsque vous travaillez sur de grands jeux de résultats.
Insertion, mise à jour et suppression d’enregistrements
QSqlQuery peut exécuter des instructions SQL arbitraires, et pas seulement des requêtes de type ` SELECT`. L’exemple suivant insère un enregistrement dans une table à l’aide de ` INSERT` :
QSqlQuery query;
query.exec("INSERT INTO employee (id, name, salary) "
"VALUES (1001, 'Thad Beaumont', 65000)");Si vous souhaitez insérer plusieurs enregistrements à la fois, il est souvent plus efficace de séparer la requête des valeurs réelles à insérer. Pour ce faire, vous pouvez utiliser des espaces réservés. Qt prend en charge deux syntaxes d'espaces réservés : la liaison nommée et la liaison positionnelle. Voici un exemple de liaison nommée :
QSqlQuery query;
query.prepare("INSERT INTO employee (id, name, salary) "
"VALUES (:id, :name, :salary)");
query.bindValue(":id", 1001);
query.bindValue(":name", "Thad Beaumont");
query.bindValue(":salary", 65000);
query.exec();Voici un exemple de liaison par position :
QSqlQuery query;
query.prepare("INSERT INTO employee (id, name, salary) "
"VALUES (?, ?, ?)");
query.addBindValue(1001);
query.addBindValue("Thad Beaumont");
query.addBindValue(65000);
query.exec();Ces deux syntaxes fonctionnent avec tous les pilotes de base de données fournis par Qt. Si la base de données prend en charge cette syntaxe de manière native, Qt transmet simplement la requête au SGBD ; dans le cas contraire, Qt simule la syntaxe des espaces réservés en prétraitant la requête. La requête effective qui sera finalement exécutée par le SGBD est disponible sous la forme QSqlQuery::executedQuery().
Lors de l'insertion de plusieurs enregistrements, il suffit d'appeler QSqlQuery::prepare() une seule fois. Ensuite, vous appelez bindValue() ou addBindValue() suivi de exec() autant de fois que nécessaire.
Outre les performances, l'un des avantages des espaces réservés est qu'ils permettent de spécifier facilement des valeurs arbitraires sans avoir à se soucier de l'échappement des caractères spéciaux.
La mise à jour d'un enregistrement s'effectue de la même manière que son insertion dans une table :
QSqlQuery query;
query.exec("UPDATE employee SET salary = 70000 WHERE id = 1003");Vous pouvez également utiliser la liaison par nom ou par position pour associer des paramètres à des valeurs réelles.
Enfin, voici un exemple d'instruction « DELETE » :
QSqlQuery query;
query.exec("DELETE FROM employee WHERE id = 1007");Transactions
Si le moteur de base de données sous-jacent prend en charge les transactions, la fonction ` QSqlDriver::hasFeature` (QSqlDriver::Transactions) renverra `true`. Vous pouvez utiliser la fonction ` QSqlDatabase::transaction()` pour lancer une transaction, suivie des commandes SQL que vous souhaitez exécuter dans le contexte de cette transaction, puis soit ` QSqlDatabase::commit()`, soit ` QSqlDatabase::rollback()`. Lorsque vous utilisez des transactions, vous devez démarrer la transaction avant de créer votre requête.
Exemple :
QSqlDatabase::database().transaction();
QSqlQuery query;
query.exec("SELECT id FROM employee WHERE name = 'Torild Halvorsen'");
if (query.next()) {
int employeeId = query.value(0).toInt();
query.exec("INSERT INTO project (id, name, ownerid) "
"VALUES (201, 'Manhattan Project', "
+ QString::number(employeeId) + ')');
}
QSqlDatabase::database().commit();Les transactions peuvent être utilisées pour garantir l’atomicité d’une opération complexe (par exemple, la recherche d’une clé étrangère et la création d’un enregistrement), ou pour permettre d’annuler une modification complexe en cours d’exécution.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.