SQL 2 Varianten Welche ist sinnvoller?

Dein Thema passt einfach in kein Forum? Dann probiers mal hier.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Klar kriegst du einen leeren String, weil nämlich next() nur bei einem SELECT (QSqlQuery::isSelect()) und isActive() true returned und deshalb nie in die Schleife einsteigt.
Wie sieht denn dein DB-Layout aus? Hat deine "int ID"-Spalte auch ein "primary key autoincrement"?
Bei dem Weg über "SELECT last_insert_rowid();" musst du natürlich auf next() ResultSet stellen, um an den Wert zu kommen, aber das wird wohl lastInsertId() auch so machen.
Nvidia
Beiträge: 238
Registriert: 22. Februar 2010 21:23

Beitrag von Nvidia »

oh das ist so kompliziert.
nein ich hab keine spalte mit primery key gemacht, weil nach der sqlite doku jeder Table automatisch eine ROWID hat auto increment nutzt.

Ja aber in dem Beispiel in der qt doku qsqlquery machen die das mit dem next() auch so.
und außerdem hab ich doch select geschrieben, aber das wird ja gleich ausgeführt und dann ist er ja fertig.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Ich hab grad noch etwas gespielt. Das mit der automatischen RowID wusste ich noch nicht :)
Ich nehme fast an, es liegt an deinem "Drumherum". Wenn ich etwas nicht raffe schreib ich mir immer kleine Testprogramme, die nur auf das Problem fokussiert sind. So schaut das dann in etwa aus:

Code: Alles auswählen

#include <QSqlDatabase>
#include <QString>
#include <QVariant>
#include <QSqlQuery>
#include <QDebug>

int main() {
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(":memory:");
    db.open();
    
    qDebug() << "No autoincrement";
    
    QSqlQuery q = db.exec("CREATE TABLE test1 (id INTEGER, name VARCHAR)");
    qDebug() << q.isActive();
    q = db.exec("INSERT INTO test1 (name) VALUES ('Semmelknödel')");
    qDebug() << "Last Id:" << q.lastInsertId().toInt();
    q = db.exec("INSERT INTO test1 (name, id) VALUES ('Ödi', 20)");
    qDebug() << "Last Id:" << q.lastInsertId().toInt();
    
    qDebug() << "With autoincrement";
    
    q = db.exec("CREATE TABLE test2 (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR)");
    qDebug() << q.isActive();
    q = db.exec("INSERT INTO test2 (name) VALUES ('Semmelknödel')");
    qDebug() << "Last Id:" << q.lastInsertId().toInt();
    q = db.exec("INSERT INTO test2 (name, id) VALUES ('Ödi', 20)");
    qDebug() << "Last Id:" << q.lastInsertId().toInt();
    
    qDebug() << "Using the SQLite ROWID";
    q = db.exec("SELECT name, id FROM test1 WHERE ROWID='1'");
    qDebug() << q.isActive();
// Das while ist eigentlich unnötig, da ROWID eindeutig ist. Ich mach es zum Testen hier trotzdem mal.
    while(q.next()) qDebug() << q.value(0).toString() << q.value(1).toInt();
    q = db.exec("SELECT name, id FROM test2 WHERE ROWID='20'");
    qDebug() << q.isActive();
    while(q.next()) qDebug() << q.value(0).toString() << q.value(1).toInt();
    
    q = db.exec("SELECT last_insert_rowid();");
    qDebug() << q.next();
    qDebug() << "Last Insert ID:" << q.value(0).toInt();
}
Geh es durch, lass es laufen, spiel damit :)
"PRIMARY KEY AUTOINCREMENT" braucht es nur, wenn du willst dass sqlite für die ROWID jene spezielle Spalte verwenden soll (oben: Table test2, COL id). Wenn du keine eigene Spalte für jene ID hast, kannst du trotzdem danach SELECTieren: "WHERE ROWID='20'" (oder so), auch wenn ROWID keine eigene, von dir angelegte Spalte ist.
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Mal davon abgesehen, daß diese Query überhaupt nichts tun dürfte außer einen Fehler zu melden:

Code: Alles auswählen

QSqlQuery query("INSERT into person (name)"
                    "VALUES ("+line->text()+")"); 
Aber dazu müßte man sich ja mal die Datenbank-Logs oder den zurückgemeldeten Fehler ansehen.
Nvidia
Beiträge: 238
Registriert: 22. Februar 2010 21:23

Beitrag von Nvidia »

ok danke das sieht supper aus und klappt auch gut.
Aber du erstellest deine querys anderes als ich.
Ich hab die Querys in einer anderen Klasse und kann nicht auf db.exec zugreifen.

QSqlQuery q2("INSERT INTO group (groupname) VALUES ('Hallo')");
qDebug() << q2.isActive();
qDebug() << q2.lastInsertId().toInt();

Das hier liefert immer false und 0.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Nvidia hat geschrieben:Ich hab die Querys in einer anderen Klasse und kann nicht auf db.exec zugreifen.
Schau dir die Doku zu QSqlQuery an. Speziell die Konstruktoren. Interessieren tut dich der zweite, das ist der den du verwendest. 1. Param = der Query, zweiter Param = die db. Schau dir durch was da passiert, du brauchst das db-Objekt gar nicht.
Trotzdem ist deine Aussage nicht korrekt ;)
QSqlDatabase verwaltet für dich alle Verbindungen. Schau dir die Doku zu QSqlDatabase::addDatabase an. 1. Param = der Treibername, 2. Param = connectionName. Du kannst mit passendem connectionName von überall aus das db-Objekt holen über QSqlDatabase::database(). Gib keinen an, und du bekommst die defaultConnection (das ist eh das was du bisher machst).
Nvidia
Beiträge: 238
Registriert: 22. Februar 2010 21:23

Beitrag von Nvidia »

Code: Alles auswählen

QSqlDatabase db = QSqlDatabase::database("test");
    db.open();
    QSqlQuery q2 = db.exec("CREATE TABLE test1 (id INTEGER, name VARCHAR)");
    qDebug() << q2.isActive();
    q2 = db.exec("INSERT INTO group (groupname) VALUES ('Hallo')");
    qDebug() << q2.isActive();
    qDebug() << q2.lastInsertId().toInt();
ok das klingt gut. Warum ist die Datenbank schon wieder zu?
QSqlQuery::exec: database not open
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Nvidia hat geschrieben:ok das klingt gut. Warum ist die Datenbank schon wieder zu?
QSqlQuery::exec: database not open
Das wissen nur die Götter...
Wie erstellst du deine DB? Zeig mal die dazugehörige Zeile mit dem "addDatabase()", und wie du die einrichtest. Nennst du die Verbindung denn auch "test" beim Erstellen?
Nvidia
Beiträge: 238
Registriert: 22. Februar 2010 21:23

Beitrag von Nvidia »

Code: Alles auswählen

static bool database()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE","test");
    db.setDatabaseName("hallo");
    if (!db.open())
    {
        ...
    }
....

}
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Und führst du database() auch aus? Wenn ich mir nämlich ein nicht existentes db-Objekt aus den verwalteten hole, krieg ich das selbe Verhalten:

Code: Alles auswählen

>>> db = QSqlDatabase.database("ich_existiere_nicht")
>>> db.open()
False
>>> db.exec_("SELECT last_insert_rowid();")
QSqlQuery::exec: database not open
<PyQt4.QtSql.QSqlQuery object at 0x7f919855eef0>
Ist zwar aus der Python-Console, aber das macht ja nix ;)
Gibt db.open() auf deine "test"-db auch false?
BTW sollte ein neuerliches open() nicht nötig sein, wenn die db eh schon geöffnet wurde.
Nvidia
Beiträge: 238
Registriert: 22. Februar 2010 21:23

Beitrag von Nvidia »

so die fehler meldungen haben zu den tables gehört in die ich am anfang erstellt habe.
Nachdem ich jetzt einiges ausgebessert hab, funktioniert alles.
COOLO endlich funktioniert die Datenbank.
danke nvidia
Antworten