Ausführen von SQL-Anweisungen
Die Klasse QSqlQuery bietet eine Schnittstelle zum Ausführen von SQL-Anweisungen und zum Navigieren durch die Ergebnismenge einer Abfrage.
Die im nächsten Abschnitt beschriebenen Klassen QSqlQueryModel und QSqlTableModel bieten eine übergeordnete Schnittstelle für den Zugriff auf Datenbanken. Wenn Sie mit SQL nicht vertraut sind, sollten Sie direkt zum nächsten Abschnitt(Verwendung der SQL-Modell-Klassen) übergehen.
Ausführen einer Abfrage
Um eine SQL-Anweisung auszuführen, erstellen Sie einfach ein QSqlQuery Objekt und rufen QSqlQuery::exec() wie folgt auf:
QSqlQuery query; query.exec("SELECT name, salary FROM employee WHERE salary > 50000");
Der QSqlQuery Konstruktor akzeptiert ein optionales QSqlDatabase Objekt, das angibt, welche Datenbankverbindung verwendet werden soll. Im obigen Beispiel geben wir keine Verbindung an, also wird die Standardverbindung verwendet.
Wenn ein Fehler auftritt, gibt exec() false
zurück. Der Fehler ist dann als QSqlQuery::lastError() verfügbar.
Navigieren in der Ergebnismenge
QSqlQuery ermöglicht den Zugriff auf die Ergebnismenge um jeweils einen Datensatz. Nach dem Aufruf von exec() befindet sich der interne Zeiger von QSqlQuery eine Position vor dem ersten Datensatz. Wir müssen QSqlQuery::next() einmal aufrufen, um zum ersten Datensatz zu gelangen, dann next() wiederholt, um auf die anderen Datensätze zuzugreifen, bis false
zurückgegeben wird. Hier ist eine typische Schleife, die alle Datensätze der Reihe nach durchläuft:
while (abfrage.weiter()) { QString name = query.value(0).toString(); int salary = query.value(1).toInt(); qDebug() << name << salary; }
Die Funktion QSqlQuery::value() gibt den Wert eines Feldes im aktuellen Datensatz zurück. Felder werden als nullbasierte Indizes angegeben. QSqlQuery::value() gibt einen QVariant zurück, einen Typ, der verschiedene C++- und Core-Qt-Datentypen wie int
, QString und QByteArray enthalten kann. Die verschiedenen Datenbanktypen werden automatisch auf das nächstgelegene Qt-Äquivalent abgebildet. Im Codeschnipsel rufen wir QVariant::toString() und QVariant::toInt() auf, um Varianten in QString und int
umzuwandeln.
Einen Überblick über die empfohlenen Typen für die Verwendung mit Qt-unterstützten Datenbanken finden Sie in dieser Tabelle.
Sie können innerhalb des Datensatzes mit QSqlQuery::next(), QSqlQuery::previous(), QSqlQuery::first(), QSqlQuery::last() und QSqlQuery::seek() navigieren. Der aktuelle Zeilenindex wird von QSqlQuery::at() zurückgegeben, und die Gesamtzahl der Zeilen in der Ergebnismenge ist für Datenbanken, die dies unterstützen, als QSqlQuery::size() verfügbar.
Um festzustellen, ob ein Datenbanktreiber ein bestimmtes Merkmal unterstützt, verwenden Sie QSqlDriver::hasFeature(). Im folgenden Beispiel rufen wir QSqlQuery::size() auf, um die Größe einer Ergebnismenge zu ermitteln, wenn die zugrundeliegende Datenbank dieses Merkmal unterstützt; andernfalls navigieren wir zum letzten Datensatz und verwenden die Position der Abfrage, um uns zu sagen, wie viele Datensätze es gibt.
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; }
Wenn Sie innerhalb einer Ergebnismenge navigieren und next() und seek() nur zum Vorwärtsblättern verwenden, können Sie QSqlQuery::setForwardOnly(true) aufrufen, bevor Sie exec() aufrufen. Dies ist eine einfache Optimierung, die die Abfrage bei großen Ergebnismengen erheblich beschleunigen kann.
Einfügen, Aktualisieren und Löschen von Datensätzen
QSqlQuery kann beliebige SQL-Anweisungen ausführen, nicht nur SELECT
. Das folgende Beispiel fügt mit INSERT
einen Datensatz in eine Tabelle ein:
QSqlQuery query; query.exec("INSERT INTO employee (id, name, salary) " "VALUES (1001, 'Thad Beaumont', 65000)");
Wenn Sie viele Datensätze gleichzeitig einfügen wollen, ist es oft effizienter, die Abfrage von den tatsächlich einzufügenden Werten zu trennen. Dies kann durch die Verwendung von Platzhaltern erreicht werden. Qt unterstützt zwei Platzhalter-Syntaxen: named binding und positional binding. Hier ist ein Beispiel für benanntes Binden:
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();
Hier ist ein Beispiel für positionelles Binden:
QSqlQuery query; query.prepare("INSERT INTO employee (id, name, salary) " "VALUES (?, ?, ?)"); query.addBindValue(1001); query.addBindValue("Thad Beaumont"); query.addBindValue(65000); query.exec();
Beide Syntaxen funktionieren mit allen von Qt bereitgestellten Datenbanktreibern. Wenn die Datenbank die Syntax nativ unterstützt, leitet Qt die Abfrage einfach an das DBMS weiter; andernfalls simuliert Qt die Platzhalter-Syntax, indem es die Abfrage vorverarbeitet. Die eigentliche Abfrage, die schließlich vom DBMS ausgeführt wird, ist als QSqlQuery::executedQuery() verfügbar.
Wenn Sie mehrere Datensätze einfügen, müssen Sie QSqlQuery::prepare() nur einmal aufrufen. Danach rufen Sie bindValue() oder addBindValue() gefolgt von exec() so oft wie nötig auf.
Neben der Leistung besteht ein Vorteil von Platzhaltern darin, dass Sie auf einfache Weise beliebige Werte angeben können, ohne sich um das Escaping von Sonderzeichen kümmern zu müssen.
Das Aktualisieren eines Datensatzes ist ähnlich wie das Einfügen in eine Tabelle:
QSqlQuery query; query.exec("UPDATE employee SET salary = 70000 WHERE id = 1003");
Sie können auch benannte oder positionale Bindungen verwenden, um Parameter mit aktuellen Werten zu verknüpfen.
Zum Schluss noch ein Beispiel für eine DELETE
-Anweisung:
QSqlQuery query; query.exec("DELETE FROM employee WHERE id = 1007");
Transaktionen
Wenn die zugrunde liegende Datenbankmaschine Transaktionen unterstützt, gibt QSqlDriver::hasFeature(QSqlDriver::Transactions) den Wert true zurück. Sie können QSqlDatabase::transaction() verwenden, um eine Transaktion zu starten, gefolgt von den SQL-Befehlen, die Sie im Rahmen der Transaktion ausführen möchten, und dann entweder QSqlDatabase::commit() oder QSqlDatabase::rollback(). Wenn Sie Transaktionen verwenden, müssen Sie die Transaktion starten, bevor Sie Ihre Abfrage erstellen.
Beispiel:
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();
Transaktionen können verwendet werden, um sicherzustellen, dass ein komplexer Vorgang atomar abläuft (z. B. das Nachschlagen eines Fremdschlüssels und das Erstellen eines Datensatzes), oder um eine Möglichkeit zu bieten, eine komplexe Änderung mittendrin abzubrechen.
© 2025 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.