Datenbankanbindung für Qt
Willemers Informatik-Ecke
Qt
Weitere Themen

Die Basis: QtSql

Das Modul QtSql muss in der Projektdatei explizit geladen werden.
QT  += core gui sql
Die Headerdate QtSql wird eingebunden.

Für jede Datenbank muss ein eigener Treiber eingebunden werden. Unter Linux müssen sie als Extra-Paket wie etwa libqt-sql aus dem Repository installiert werden.

Treibername Datenbanksystem
QPSQL PostgreSQL
QMYSQL MySQL
QSQLITE SQLite
QOCI Oracle Call Interface
QODBC ODBC: universeller Treiber von Microsoft
QDB2 IBM DB2
QTDS Sybase Adaptive Server

Connection wird durch Aufruf von addDatebase erreicht. Als Parameter erhält sie den Namen des Datenbanktreibers und optional den Namen der anzusprechenden Datenbank.

QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL", "KundenDB");
db.setHostName("dbserver.willemer.edu");
db.setDatabaseName("KundenDB");
db.setUserName("dbuser");
db.setPassword("ganzgeheim");
if (!db.open()) {
    cerr << db.lastError().text() << endl;
    return;
}

Besonderheit SQLite

SQLite kann die Datenbank ohne äußere Anbindung in einer einfachen Datei speichern.
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("kunden.db");
Ist der Dateiname in Doppelpunkte eingeschlossen, wird sie nur im Hauptspeicher gehalten. Die Daten sind nach dem Verlassen des Programms verloren.

SQL-Befehle ausführen

Mit der Funktion exec() kann ein Befehl an die Datenbank gesandt werden. Der folgende Ausschnitt löscht alle Kunden, die den Namen Johann tragen.

QSqlQuery query;
query.exec("DELETE FROM kunde WHERE name = 'Johann'");
Beim Einfügen von Daten können die Datenbankvariablen durch Voranstellen eines Doppelpunkts mit Namen versehen werden, die vom Programm aus mit der Funktion bindValue an Werte innerhalb des Programms verbunden werden.
query.prepare("INSERT INTO kunde (name, adresse) VALUES(:name, :adresse)");
query.bindValue(":name", "Johann");
query.bindValue(":adresse", "Holzweg Buxtehude");
query.exec();
Die Zeichenketten heißen unter Qt übrigens QString.

Abfragen

Anfragen erfolgen über die Klasse QSqlQuery. Konstruktor erhält SQL-Anfrage als Parameter. Mit exec() lassen sich später weitere Anfragen stellen. first() liefert ersten Datensatz next() liefert nächsten Datensatz last() liefert letzten Datensatz seek(int) liefert den Datensatz zum Index. size() liefert die Anzahl der gefundenen Sätze.
QSqlQuery query("SELECT name, adresse FROM kunde");
QSqlRecord record = query.record();
while (query.next())
{
    QString name = query.value(record.indexOf("name")).toString();
    QString adr = query.value(record.indexOf("adresse")).toString();
    cout << query.at() << ":" << name << "," << adr << endl;
}

Darstellen in einer Tabelle

Im Qt-Designer wird die Tabelle mit Model unter dem Namen tabKunden angelegt. Das Model bewirkt, dass der Inhalt der Tabelle nicht durch das Programm besetzt wird, sondern aus einem Datenmodell. In diesem Fall ist dies eine Datenbanktabelle.

Dazu wird im Programm ein QSqlTableModel angelegt, das sich aus einer QSqlDatabase speist, hier in der Variablen db.

Das Modell wird auf den Namen der Tabelle gelegt und mit einem select geladen. Anschließend wird die grafische Tabelle der ui mit dem Datenmodell verbunden.

// Tabellenview auf die Datenbank
QSqlTableModel *kundenModell = new QSqlTableModel(this, db);
kundenModell->setTable("kunde");
kundenModell->select();
ui->tabKunden->setModel(kundenModell);
Mit model->removeColumn(int) kann eine Spalte unsichtbar gemacht werden. Über den Aufruf model->setHeaderData(nr, Qt::Horizontal, tr("Name")) kann der Spalte nr eine neue Überschrift Name gegeben werden.

In der Tabelle können Werte direkt verändert werden. Sie werden in die Tabelle bei Wechsel der Zeile geschrieben. Das entspricht der Editierstrategie SqlTableModell::OnRowChange. Sie können die Strategie mit dem Aufruf von setEditStrategy ändern. Durch Übergabe des Parameters SqlTableModell::OnFieldChange wird schon beim Wechsel des Feldes (waagerecht) geschrieben, bei SqlTableModell::OnManualSubmit werden alle Änderungen erst dann übernommen, wenn irgendwann der Aufruf submitAll() aufgerufen wird. Abgebrochen werden die Änderungen mit revertAll().

Wird QSqlRelationalTabletModel verwendet, werden Referenzen einer Tabelle so aufgelöst, dass der Fremdschlüssel angezeigt wird und durch eine Combobox änderbar ist.

Mit dem QSqlQueryModel können auch SELECT-Anfragen in einer Tabelle dargestellt werden, die nicht als Tabelle vorliegen.