MySql abfragen mit Qt

Alles rund um die Programmierung mit Qt
Antworten
Tuxing
Beiträge: 52
Registriert: 28. Oktober 2009 11:13

MySql abfragen mit Qt

Beitrag von Tuxing »

Hallo Community,
ich bin aktuell dabei ein Programm zu schreiben, dass sich zu einer Datenbank verbindet und erstmal nur Werte ausließt. Die Verbindung zur Datenbank hab ich bereits auch erfolgreich hergestellt ( Es ist eine MySQL4 - Datenbank) allerdings bekomm ich immer einen Fehler beim Abfragen von Tabellen Werten.

Der Fehler, der auf der Console erscheint lautet wie folgt:

"QSqlQuery::value: not positioned on a vaid record"

Das Pogramm stürzt dadurch allerdings nicht ab, es läuft weiter.

Ich weiß leider nicht was mein Rechner mir damit sagen will.

Der Quellcode dazu ist der folgende:


void test_query()
{
// Connect to Database
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL3");
db.setHostName("127.0.0.1");
db.setDatabaseName("dbname");
db.setUserName("dbusername");
db.setPassword("dbpassword");
db.setPort(dbport);

bool ok = db.open();

// ok hat den wert true, die Verbindung ist erfolgreich zur Datenbank
// aufgebaut.
// Zum test lasse ich alle Tabellen ausgeben die in der Datenbank sind

foreach (QString item, db.tables())
{
cout << "Tabelle: " << item.toStdString() << endl;
}

// Ausgabe der Tabellen war erfolgreich

QSqlQuery query("SELECT name FROM jos_users",db);

bool ok2 = query.exec();

// ok2 hat den Wert true, von daher gehe ich mal davon aus, dass
// die abfrage erfolreich ausgeführt wurde

cout << query.value(0).toString().toStdString() << endl;

query.finish();

db.close();
}

Wenn ich die Zeile "cout << query.value(0).toString().toStdString() << endl;" auskommentiere kommt der Fehler nicht. Aber irgendwie muss ich ja jetzt an den Wert herankommen den ich aus der Datenbank abgefragt habe. In dem Fall alle namen der Tabelle jos_users

Ich hab auch mal wie es in der Dokumentation steht folgendes versucht:

while (quey.next() )
{
cout << query.value(0).toString().toStdString() << endl;
}

statt nur die Ausgabe, allerdings stürzt das Programm dann bei query.next() ab. Vll hilft das jemandem weiter.


Danke schonmal für Lösungsideen.

Gruß
AuE
Beiträge: 918
Registriert: 5. August 2008 10:58

Beitrag von AuE »

das liegt daran das der zeiger auf die Daten vor/hinter einem gültigen datensatz liegt!
das mit den query.next() ist also nötig.

Bei deiner abfrage weiß ich nicht ob name evtl ein keyword ist.... mach doch einfach tst halber mal die abfrage "select count(*) from jos_users"

oder des bsp hier aus der doc:

Code: Alles auswählen

QSqlQuery q("select * from employees");
 QSqlRecord rec = q.record();

 qDebug() << "Number of columns: " << rec.count();

 int nameCol = rec.indexOf("name"); // index of the field "name"
 while (q.next())
     qDebug() << q.value(nameCol).toString(); // output all names
Tuxing
Beiträge: 52
Registriert: 28. Oktober 2009 11:13

Beitrag von Tuxing »

Hallo,
ich hab versucht die Vorschläge von AuE umzusetzen, jedoch ohne Erfolg.
Folgendes habe ich versucht:

Code: Alles auswählen


void klasse::test_query
{
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL3");
db.setHostName("127.0.0.1");
db.setDatabaseName("dbname");
db.setUserName("dbusername");
db.setPassword("dppassword");
db.setPort(dbport);

QSqlQuery query("select username from jos_users");
bool ok2 = query.exec();

QSqlRecord rec = query.record();
cout << "number of columns:  " << rec.count() << endl;

int nameCol = rec.indexOf("username");
cout << "Index ausgabe:  " << nameCol << endl;

cout << "Inhalt:  " << query.value(nameCol).toString().toStdString() << endl;

query.finish();
db.close();

}


Wenn ich die Abfrage mit einem * schreibe um alle Spalten abzufragen, liefert mir query.exec() den Wert fase zurück, von daher gehe ich mal davon aus dass das nicht funktioniert hat. Acuh wenn ich zb. einen Spaltennamen eingebe, den es nicht gibt liefert exec() den Wert false. Da er bei "uersname" den Wert true ausgibt, scheint er in der Taballe die Spalte ja gefunden zu haben.
Bei "Number of Columns" bekomme ich dann den Wert 1, dass heißt ja schonmal, dass die Spalte dich ich gewählt hab anscheinend gefunden wurde.
Ich bekomme es jetzt jedoch nicht hin mir die Werte ausgeben zu lassen.

Code: Alles auswählen

rec.indexOf("username");   
gibt mir den Wert 0 zurück, und wenn ich dann:

Code: Alles auswählen

cout << "Inhalt:  " << query.value(nameCol).toString().toStdString() << endl;
ausführe bekomme ich wieder meine Fehlermeldung:
"QSQLQuery::value: not positioned on a valid record".
Bei dem Befehl query.next() stürzt das Programm weiterhin ab.
Ich habe leider keine Idee mehr woran es noch liegen kann. Hoffe von euch weiß noch jemand Rat..

Danke schonmal
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Ein query.next() ist zwingend erforderlich wenn du Daten haben willst. Und wenn ein Programm abstürzt, dann gibt es auch Fehlermeldung dazu. => Debugger
Tuxing
Beiträge: 52
Registriert: 28. Oktober 2009 11:13

Beitrag von Tuxing »

okay also query.next() mus drin sein um quasi zumindest das erste element zu bekommen.
Ich habden Code nochmals abgeändert (übersichtlicher und mit Fehlerabfragen):

Code: Alles auswählen



QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL3");
db.setHostName("127.0.0.1");
db.setDatabaseName("dbname");
db.setUserName("dbusername");
db.setPassword("dbpassword");
db.setPort(dbport);
	
if( db.open() )
{
        QSqlQuery query;
			
        if( query.prepare("SELECT name FROM jos_users") )
        {
             if( query.exec() )
             {
                  while (query.next()) 
	  {
                      cout << "Ausgabe:  " << query.value(0).toString 
                      ().toStdString() << endl;
	  }
		
              query.finish();
              }
          }
	
          db.close();
}

Der Debugger schmeist bei query.next() folgende Fehlermeldung:
Unbehandelte Ausnahme bei 0x04988757 (libmysql.dll) in MyProgram.exe: 0xC0000005: Zugriffsverletzung beim Schreiben an Position 0x000000fe.
Zusammenfassend: Es funktioniert, dass die Datenbank connected wird, die Abfrage vorbereitet und die Abfage ausgeführt wird. Dann is jedoch ende .. :(

Kann es dara liegen, dass ich mit einer MySQL4 - Datenbank arbeite aber der Treiber MYSQL3 ist ??
Tuxing
Beiträge: 52
Registriert: 28. Oktober 2009 11:13

Beitrag von Tuxing »

Hallo Leute,
ich komme der Lösun näher ;) Ich hab jetzt herausgefunden, dass mein Programm in Verbindung mit einer Datenbank ( Version: 3.23.58 ) hervorragend funktioniert. Allerdings bekomm ich immer einen Absturz beim "query.next()" Befehel sobald ich mit einer Datenbank ( Version: 4.1.22 ) arbeite.
Unbehandelte Ausnahme bei 0x04998757 (libmysql.dll) in MyProgramm.exe: 0xC0000005: Zugriffsverletzung beim Schreiben an Position 0x000000fe.
Der Fehler bezieht sich auf folgenden QT-Code aus der Datei "qsql_mysql.cpp":
#if MYSQL_VERSION_ID >= 40108
mysql_stmt_data_seek(d->stmt, i);
Wegen der if-Bedingung kam ich auch auf die Idee mal eine Datenbank mit Version < 40108 zu benutzen, mit der es dann nicht zu diesem Problem kommt.



Außerdem Funktioniert sowas wie query.exec("select *from jos_users")
nicht. Also ich kann keine Abfragen mit * verschicken. Bei der Arbeit mit einer 3-er Datenbank geht das.

Mein Code der mit der 3-er funktioniert aber nich mit der 4-er sieht folgendermaßen aus:

Code: Alles auswählen


void test::db 
{
   QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
   db.setHostName("127.0.0.1");
   db.setDatabaseName("dbname");
   db.setUserName("dbusername");
   db.setPassword("dbpassword");
   db.setPort(dbport);

   if( db.open() )
   {
      QSqlQuery query;
   }


   if( query.exec("select name from jos_users") )
   {
      while (query.next()) 
      {
         cout << query.value(0).toInt() << endl;
      }

      query.finish();
   }
		
	
   db.close();
}


Wäre super wenn mir da jemand weiter helfen könnte, da ich eigentlich mit MySql 4 arbeiten wollte.

Danke
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

Tuxing hat geschrieben:Hallo Leute,
Danke
Ich machs immer nach dem Schema:

Code: Alles auswählen

int Klasse::initDb()
{
   QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
   db.setHostName("127.0.0.1");
   db.setDatabaseName("dbname");
   db.setUserName("dbusername");
   db.setPassword("dbpassword");
   db.setPort(dbport);

   if (!db.open())
   {
      QMessageBox::critical(this, "Error", "...");
      return fail;
   }

   return success;
}

int Klasse::doSomething()
{
   QSqlQuery q("select name from jos_users");

   while (q.next())
      qDebug() << query.value(0);

   return success;
}

Tuxing
Beiträge: 52
Registriert: 28. Oktober 2009 11:13

Beitrag von Tuxing »

okay für alle die vll ein ähnliches problem hatten, hier ist mein Lösung:

Der Fehler waren die MySql treiber. Ich hatte MySQL 4.x installiert und daraus das QT Plugin installiert. Anscheinend hatte der Treiber für MySQL 4 Datenbanken einen Fehler.
Das Problem war gelöst, nachdem ich MySQL 5 installiert hatte und das Plugin neu erstellt. Dann QT neu kompilieren und alles hat funktioniert.

Danke für die vielen Lösungsvorschläge
Antworten