[gelöst] SQLITE, Where Clause funktioniert nicht

Alles rund um die Programmierung mit Qt
Antworten
ThomasM
Beiträge: 5
Registriert: 8. Juni 2014 15:30

[gelöst] SQLITE, Where Clause funktioniert nicht

Beitrag von ThomasM »

Hallo zusammen,

direkt: ich habe gegoogelt und schon ein paar weitere Freunde gefragt, die mir allerdings nicht weiterhelfen konnten. Daher wende ich mich an das QtForum. Ich habe ein Problem mit meiner QSQLITE Query Anfrage. Es geht im speziellen um Folgendes:

Ich verwalte derzeit über Qt eine kleine Datenbank. Einträge hinzufügen über den Befehl

Code: Alles auswählen

if(!q.prepare("INSERT INTO "+Klassentyp+" (sName, sDescription, dCreate, dLastModified, dCustom, tBest, tTotal, qPicture, iMassstab, iTotalLaps, dDummy) VALUES (:sName, :sDescription, :dCreate, :dLastModified, :dCustom, :tBest, :tTotal, :qPicture, :iMassstab, :iTotalLaps, :dDummy)")) {
        QSqlError err = q.lastError();
        cout << "\n\n FEHLER BEIM ABSPEICHERN: \n" +err.text().toStdString() << "\n\n";
        QMessageBox::critical(0,"Datenbankfehler","Fehler in der Datenbank! Wollte basic::vDBSave ausfuehren und bin im ersten Block hängen geblieben. Der SQL Error gibt zurück: \n" +err.text());

    }
// …
if(!q.exec()) {
        QSqlError err = q.lastError();
        cout << "Fehler beim abspeichern: in basic::vDBSave ganz am Ende habe ich folgenden Fehler: \n" << err.text().toStdString() << "\n";
        return;
    }
funktioniert ohne Probleme und ich sehe auch direkt Änderungen in der GUI.
Möchte ich allerdings Einträge Löschen oder auch nur Updaten, so kann ich diese Funktion nicht korrekt ausführen. Zwar gibt mir q.lastError().text() keinen Fehler wieder und die Anfrage des Querys in Form von

Code: Alles auswählen

QString query = "DELETE FROM "+Klassentyp+" WHERE ID = '"+QString::number(iID)+"'";

    // Den Query Ausführen und auf Fehler gucken.
    if(!q.exec(query)) {
        QSqlError err = q.lastError();
        QMessageBox::critical(0,"Datenbankfehler","Fehler in der Datenbank! Wollte vDBErase ausfuehren und bin im schreibenden Block hängen geblieben. Der SQL Error gibt zurück: \n" +err.text());
    }
(Wobei Klassentyp als Tabellenname ersetzt wird und QString::numer(iID) gibt mir den entsprechenden ID Wert des Eintrages aus vorherigem Programmabschnitt (funktioniert auch)).

Auch im Debugger finde ich keinen Fehler, das Programm stürzt nicht ab, nichts besonderes. Nur die Anfrage an die Datenbank funktioneiert auf Gedeih und Verderben nicht. Wende ich allerdings die Where-Condition ab und schreibe z.B.

Code: Alles auswählen

delete from table Fahrer
wird alles in Fahrer gelöscht, so soll es ja auch sein. Ändere ich dann jedoch das ganze mit dem Zusatz und schreibe

Code: Alles auswählen

delete from table Fahrer where ID = 2
funktioniert das nicht und ich lande dort, was ich oben beschrieben habe.

Hat da jemand einen Lösungsvorschlag? Für Rückfragen stehe ich natürlich jederzeit offen und freue mich auch darüber!

Vielen Dank für eure Antworten!
Thomas
Zuletzt geändert von ThomasM am 18. Juni 2014 14:05, insgesamt 1-mal geändert.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: SQLITE, Where Clause funktioniert nicht

Beitrag von Christian81 »

Ich bin mir ziemlich sicher dass "delete from table Fahrer where ID = 2" funktioniert - du versuchst allerdings "delete from table Fahrer where ID = '2'" auszuführen ...
btw: SQL-Statements als Strings zusammenbauen öffnet SQL-Injection die Tür ...
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
ThomasM
Beiträge: 5
Registriert: 8. Juni 2014 15:30

Re: SQLITE, Where Clause funktioniert nicht

Beitrag von ThomasM »

Danke für die Antwort!

Ich habe beide Versionen schon ausprobiert und leider Funktioniert weder

Code: Alles auswählen

delete from fahrer where ID = 2
noch

Code: Alles auswählen

delete from fahrer where ID = '2'
gibt es sonst noch Möglichkeiten wie ich dem Fehler auf die Spur kommen kann?


PS:Gut, dass du auf die SQL Injections erwähnst. Dennoch bleibe ich dabei, denn das Programm werde nur ich nutzen und darin speichere ich keine vertraulichen Daten ab.
softwaremaker
Beiträge: 149
Registriert: 1. April 2009 19:25

Re: SQLITE, Where Clause funktioniert nicht

Beitrag von softwaremaker »

was ist ID ?
Hast du das Attribut in der Tabelle selbst definiert und welcher Datentyp?
ThomasM
Beiträge: 5
Registriert: 8. Juni 2014 15:30

Re: SQLITE, Where Clause funktioniert nicht

Beitrag von ThomasM »

ID ist ein INT PRIMARY KEY. Die Tabelle habe ich selbst erstellt mit

Code: Alles auswählen

if(!sqlTableList.contains("Fahrer")) {
        q.prepare("CREATE TABLE Fahrer(ID INT PRIMARY KEY, sName TINYTEXT, sDescription MEDIUMTEXT, dCreate DATE, dLastModified DATE, dCustom DATE, tBest TIME, tTotal TIME, qPicture TEXT, iMassstab INT, iTotalLaps INT, dDummy DOUBLE)");
        if(!q.exec()) {
            QSqlError err = q.lastError();
            qDebug() << err.text() << endl;
        }
        cout << "existiert noch nicht. Habe sie jetzt angelegt." << endl;
    } else
       cout << "existiert" << endl;
softwaremaker
Beiträge: 149
Registriert: 1. April 2009 19:25

Re: SQLITE, Where Clause funktioniert nicht

Beitrag von softwaremaker »

Jedoch gibst du beim INSERT keine ID an!!!
Wenn du willst, dass Sqlite automatisch die ID vergibt, dann muss"AUTOINCREMENT" dazu, also
CREATE TABLE Fahrer(ID INTEGER PRIMARY KEY AUTOINCREMENT, ...
Bei INSERT INTO erzeugt Sqlite selbst eine ID, diese kannst du mit QSqlQuery::lastInsertId() ermitteln.

Ich benutze zum Testen etc. http://sqlitestudio.pl
ThomasM
Beiträge: 5
Registriert: 8. Juni 2014 15:30

Re: SQLITE, Where Clause funktioniert nicht

Beitrag von ThomasM »

Lieber softwaremaker: herzlichen Dank für die Aufdeckung meines blöden Fehlers!

Habe meine Datenbank berichtigt und bin jetzt auch zu einem Ergebnis gekommen, sodass ich es hier auch kurz der Vollständigkeit halber vorstellen kann.

Nachdem ich also meine Datenbank erstelle mit

Code: Alles auswählen

CREATE TABLE Strecke(ID INTEGER PRIMARY KEY AUTOINCREMENT, sName TINYTEXT , …
lasse ich mir diese auch in Dropboxen ausgeben, welche ich einmal mit dem Tinytext aus sName und einmal mit der ID füttere. Das sieht dann so aus (ui->rennen_strecke und ui->liste sind beides ComboBoxen):

Code: Alles auswählen

if(!q.exec("SELECT * FROM Strecke ORDER BY ID ASC"))
        if(q.lastError().number() != QSqlError::NoError)
            cout << "Datenbankfehler: " << q.lastError().text().toStdString() << endl;

    while(q.next()) {
        ui->rennen_strecke->addItem(q.value(1).toString(),q.value(0).toInt());
        if(Topic == "Strecke") {
            ui->liste->addItem(q.value(1).toString(),q.value(0).toInt());
            cout << "Name:\t" << q.value(1).toString().toStdString() << "\t ID:" << q.value(0).toInt() << endl;
        }
    }
So kann ich dann später recht einfach über ein Auslesen der ID in Form von

Code: Alles auswählen

basic* item = new basic(ui->liste->currentData().toInt(),Topic,db);
    item->vDBRead();
wo ich im Konstruktor den Datensatz übergebe, welcher die eigentliche ID beschreibt, sowie die Datenbankschnittstelle in Form von db. Topic ist bei mir ein Platzhalter und bezeichnet nichts anderes als die Tabellennamen, sodass ich für gleiche Operationen in verschiedenen Tabellen nicht unbedingt noch verschiedene Funktionen einbetten muss. item->vDBRead() erklärt sich glaube ich von selbst.

Ich freue mich, dass es so funktioniert und das Forum doch immer wieder eine nützliche Hilfe ist!

Liebe Grüße
Thomas

Edit: SQLiteStudio ist der Hammer! Man kann sogar in die einzelne .app (auf dem Mac) reingehen und den aktuellen Status der Datenbank überprüfen. Schicke schicke Sache! Auch ein Dankeschön hierfür!
softwaremaker
Beiträge: 149
Registriert: 1. April 2009 19:25

Re: SQLITE, Where Clause funktioniert nicht

Beitrag von softwaremaker »

Prima das es geklappt hat.
Besser wäre statt des * bei "SELECT * FROM Strecke ORDER BY ID ASC" direkt die Attribute anzugeben, dann ist die Zuordnung zum Index über q.value(0) und q.value(1) sicher (falls sich mal an der Tabelle was ändert bzw. kann die Reihenfolge in der Rückgabe mit * laut SQL-Norm beliebig sein so weit ich weiß).
Antworten