INSERT in eine Access MDB mit QSqlQuery

Alles rund um die Programmierung mit Qt
Antworten
QT-Junkee
Beiträge: 18
Registriert: 14. März 2007 14:59

INSERT in eine Access MDB mit QSqlQuery

Beitrag von QT-Junkee »

Hallo.

Aus der Qt Doku habe ich folgendes Beispiel rausgesucht, welches ich in mein Programm implementieren möchte:

Code: Alles auswählen

        QSqlQuery query;
        query.prepare("INSERT INTO person (id, forename, surname) "
                      "VALUES (?, ?, ?)");
        query.bindValue(0, 1001);
        query.bindValue(1, "Bart");
        query.bindValue(2, "Simpson");
        query.exec(); 
Ich habe den Snippet in meinem Programm so umgesetzt:

Code: Alles auswählen

...
QSqlQuery query;
query.prepare("INSERT INTO T_Text ( [Language], [No] , [Text]) "
			"VALUES ( ?, ?, ?)");
query.bindValue(0, specificLanguage.toInt());
query.bindValue(1, specificNumber.toInt());
query.bindValue(2, specificText);
bool check = query.exec();
...
In der Testdatenbank existieren 3 Spalten (Language, No und Text <- alles von Microsoft Access reservierte Wörter, deswegen in den eckigen Klammern).
Die Werte specificLanguage und specificNumber sind Strings, die in der Datenbank aber Integer sein müssen, deswegen toInt().

Seltsamerweise klappt der Insert nicht, der Compiler liefert immer den String
QODBCResult::exec: unable to bind variable: [Microsoft][ODBC Microsoft Access Driver]Ungültiger Genauigkeitswert , zurück.

Hat jemand einen Vorschlag, wie man den INSERT erfolgreich durchführen könnte? Was mache ich falsch?
macman
Beiträge: 1738
Registriert: 15. Juni 2005 13:33
Wohnort: Gütersloh
Kontaktdaten:

Re: INSERT in eine Access MDB mit QSqlQuery

Beitrag von macman »

QT-Junkee hat geschrieben:QODBCResult::exec: unable to bind variable: [Microsoft][ODBC Microsoft Access Driver]Ungültiger Genauigkeitswert , zurück.
Also wirklich. Eine deutsche Fehlermeldung kann wohl kaum von Qt kommen, also wird sie vom ODBC-Treiber kommen. Google mit 'Ungültiger Genauigkeitswert' füttern und gleich der erste Treffer verweist auf eine Microsoft-Seite. http://www.google.de/search?q=Ung%C3%BC ... wert&hl=de

Mehr Hilfe gibt es nicht, das solltest Du jetzt alleine finden.
Die deutsche Schriftsprache ist case-sensitive. Außerdem gibt es eine Interpunktionsnorm. Wenn manch einer seine Programme genauso schlampig schreibt, wie sein Posting hier, dann sollte er es lieber bleiben lassen.
QT-Junkee
Beiträge: 18
Registriert: 14. März 2007 14:59

Beitrag von QT-Junkee »

@macman

Ist zwar schön und gut, in Qt gibbets aber keinen Bsp, wie man in die Funktion bindValue die Angabe TEXT(50), z.B reinbringt. Diese Funktion akzeptiert ebend 2 Parameter und der INSERT Befehl ist auch nur in dieser Version vertreten.
Ausserdem, wenn ich in diesem Forum was frage, dann habe ich ja schon gegoogelt und die Qt Doku durchgeblättert..
Wenn es keine Hilfe gibbet, wozu dann das Ganze? :?
macman
Beiträge: 1738
Registriert: 15. Juni 2005 13:33
Wohnort: Gütersloh
Kontaktdaten:

Beitrag von macman »

Dann lass es mit bindValue. Ich habe mit QSql-Klassen noch nichts gemacht, aber für mich käme für Datenbankabfragen eh nur "bool QSqlQuery::exec ( const QString & query )" in Frage. Ich bastele mir vorher einen String zusammen, den ich in einem DB-Frontend testen kann, ohne mir mit lastQuery() erst angucken zu müssen was überhaupt an die DB gegangen ist.

Du kannst also deine Querys in Access testen und dann packst Du sie als String in deine Query.
Die deutsche Schriftsprache ist case-sensitive. Außerdem gibt es eine Interpunktionsnorm. Wenn manch einer seine Programme genauso schlampig schreibt, wie sein Posting hier, dann sollte er es lieber bleiben lassen.
QT-Junkee
Beiträge: 18
Registriert: 14. März 2007 14:59

Beitrag von QT-Junkee »

Zitate aus dem Netz:
"..komplizierter wird es bei INSERT-­Anweisungen. Da man damit Werte aus
programmeigenen Datenstrukturen in die Datenbank schreibt, lässt sich die ent­sprechende SQL­Anweisung nur aufwändig als String formulieren und direkt aus­führen: Deshalb geht man hier einen anderen Weg: Wir speichern die mit Platzhal­tern ausgestattete Anfrage mit prepare() im Query­Objekt:
// sqlexample/main.cpp (fortgesetzt)
query.prepare("INSERT INTO mitarbeiter (nachname, vorname, abteilung)"
"VALUES(:nachname, :vorname, :abteilung)");
query.bindValue(":nachname", "Hasse");
query.bindValue(":vorname", "Peter");
query.bindValue(":abteilung", 3);
query.exec();
Die aus der Oracle­Welt stammenden benannten Platzhalter im VALUES-­Teil des SQL­Kommandos beginnen jeweils mit einem Doppelpunkt. Mit dem Kommando bindValue() ersetzen wir sie durch die konkreten Werte.
Auch mit den aus ODBC bekannten unbenannten Parametern kann QSqlQuery umgehen. Jeder bindValue()­Aufruf ersetzt der Reihe nach eines der Fragezeichen:
// sqlexample/main.cpp (fortgesetzt)
query.prepare("INSERT INTO mitarbeiter (nachname, vorname, abteilung)"
"VALUES(?, ?, ?");
query.bindValue("Schwan");
query.bindValue("Waldemar");
query.bindValue(3);
query.exec();

Möchte man die Werte nicht der Reihenfolge nach ersetzen, nutzt man folgende überladene Variante:
query.bindValue(3, 3);
query.bindValue(1, "Schwan");
query.bindValue(2, "Waldemar");
Hier gibt der erste Parameter die zu ersetzende Position, also das zu ersetzende Fragezeichen, im prepare()­String an.
Auch bei gespeicherten Prozeduren (Stored Procedures) spielt bindValue() eine zentrale Rolle, denn deren Parameter können sowohl als IN als auch als OUT dekla­riert sein. OUT deklarierte Parameter fungieren als Rückgabewert. "...


oder



SQL > Tabellenbearbeitung > Insert Into

In den vorhergehenden Abschnitten haben wir uns mit dem Aufrufen von Daten aus Tabellen beschäftigt. Wie gelangen diese Datenzeilen aber ursprünglich in die Tabellen? Um diese Frage geht es in den nächsten Abschnitten, die die Anweisungen INSERT und UPDATE behandeln.

In SQL gibt es im Wesentlichen zwei Methoden zum Einfügen (INSERT) von Daten in eine Tabelle: Bei der einen wird jeweils eine Zeile eingefügt und bei der anderen mehrere gleichzeitig. Sehen wir uns zunächst den Befehl zum Einfügen (INSERT) einzelner Datenzeilen an.

Die Syntax für die entsprechende Funktion sieht folgendermaßen aus:

INSERT INTO "Tabellen_Name" ("Spalte1", "Spalte2", ...)
VALUES ("Wert1", "Wert2", ...)

Nehmen wir an, uns liegt eine Tabelle mit der folgenden Struktur vor,

Tabelle Store_Information
Spalte Name Datentyp
store_name char(50)
Sales float
Date datetime

und wir möchten nun eine weitere Zeile mit den Umsatzdaten für Los Angeles am 10. Januar 1999 in die Tabelle einfügen. An diesem Tag erzielte das entsprechende Warenhaus einen Umsatz von ¤ 900. Wir verwenden dazu das folgende SQL-Skript:

INSERT INTO Store_Information (store_name, Sales, Date)
VALUES ('Los Angeles', 900, '10.Jan.1999')

Mit dem zweiten Typ von INSERT INTO können wir mehrere Zeilen in eine Tabelle einfügen. Im Gegensatz zum vorhergehenden Beispiel, bei dem wir eine einzelne Zeile durch Angabe der Werte für alle Spalten eingefügt haben, verwenden wir nunmehr eine SELECT-Anweisung, um die einzufügenden Daten festzulegen. Mit der Vermutung, dass dies die Verwendung von Daten aus einer anderen Tabelle impliziert, liegen Sie richtig.


Wie bei SELECT kann man hier keinen solchen String basteln...
Man muss schon mit bindValue arbeiten..
macman
Beiträge: 1738
Registriert: 15. Juni 2005 13:33
Wohnort: Gütersloh
Kontaktdaten:

Beitrag von macman »

Man kann immer einen String basteln, aber für deine Zwecke kannst Du ruhig bindValue nehmen, wenn Du willst. Um aber mal zu deinem ursprünglichen Problem bei einem Insert zu kommen. Die Fehlermeldung besagt wohl, das Datentypen nicht kompatibel sind. Kann es sein das Du einen Long-Wert in eine Integerfeld packen willst? Oder einen 60 Zeichen String in ein 50 Zeichen Feld?
Die deutsche Schriftsprache ist case-sensitive. Außerdem gibt es eine Interpunktionsnorm. Wenn manch einer seine Programme genauso schlampig schreibt, wie sein Posting hier, dann sollte er es lieber bleiben lassen.
QT-Junkee
Beiträge: 18
Registriert: 14. März 2007 14:59

Beitrag von QT-Junkee »

Die Werte, die ich mit INSERT in meine Tabelle reinkopieren möchte, sind
QString-Werte.
In der Zieldatenbank sind folgende Definitionen Pflicht:

Feldname Felddatentyp Format

Language | Zahl | Byte

No | Zahl | LongInteger

Text | Memo | ----


Für Text gibts also reichlich Platz.

Ich habe jetzt folgende Lösung zusammengesucht (Snippet aus der Qt Mailing List)
http://lists.trolltech.com/qt-interest/ ... 299-0.html

Code: Alles auswählen

int lang = specificLanguage.toInt();
				int num = specificNumber.toInt();
				query.exec( QString( "INSERT INTO T_Text ([Language], [No] , [Text])  VALUES ( %1, %2, '%3' )" ).arg(lang).arg(num).arg(specificText) );
				bool check = query.exec();
				QString checks = query.lastQuery();
Ergebnis ist wieder False, Compiler sagt:

[Microsoft][ODBC Driver Manager] Fehler in der Funktionsreihenfolge
macman
Beiträge: 1738
Registriert: 15. Juni 2005 13:33
Wohnort: Gütersloh
Kontaktdaten:

Beitrag von macman »

Funktioniert der Insert in Access?
Die deutsche Schriftsprache ist case-sensitive. Außerdem gibt es eine Interpunktionsnorm. Wenn manch einer seine Programme genauso schlampig schreibt, wie sein Posting hier, dann sollte er es lieber bleiben lassen.
QT-Junkee
Beiträge: 18
Registriert: 14. März 2007 14:59

Beitrag von QT-Junkee »

Leider nicht, zurückgeliefert wird check = false, und Compiler Fehler (genauer gesagt Access Meldung) ist:
[Microsoft][ODBC Driver Manager] Fehler in der Funktionsreihenfolge

die Werte werden nicht eingetragen. Bei dem Typen, der in der Qt Mailing List die Frage gestellt hat, hat anscheinend alles geklappt.
macman
Beiträge: 1738
Registriert: 15. Juni 2005 13:33
Wohnort: Gütersloh
Kontaktdaten:

Beitrag von macman »

Du hast ein Access-Problem, kein Qt-Problem. Also probier die Anfrage direkt in Access.
Öffne deine Datenbank in Access
Klicke im Datenbankfenster links auf Abfragen
Erstelle neue Abfrage in Entwurfsansicht
Das kleine Fenster schliessen
Oben links bei SQL auf SQL-Ansicht umschalten
Da kannst Du jetzt deine Query eingeben und rumprobieren bis es keinen Fehler mehr gibt.

Wenn es in Access funktioniert und mit Qt nicht, dann kannst Du hier noch mal nachfragen.
Die deutsche Schriftsprache ist case-sensitive. Außerdem gibt es eine Interpunktionsnorm. Wenn manch einer seine Programme genauso schlampig schreibt, wie sein Posting hier, dann sollte er es lieber bleiben lassen.
QT-Junkee
Beiträge: 18
Registriert: 14. März 2007 14:59

Beitrag von QT-Junkee »

Hi macman!

Thx für deine Access-Anleitung, habe deinen Rat auch befolgt.
Folgende Query in Access ausgeführt:

INSERT INTO T_Text ([Language], [No] , [Text]) VALUES (' 1', '97 ', 'asdvvnsaposnvod' );

hat geklappt ohne Fehler. Die Sachen werden eingefügt. Bloß weiss ich nicht, warum es nicht mit Qt Befehlen nicht geht...

QODBCResult::exec: Unable to execute statement: [Microsoft][ODBC Driver Manager] Fehler in der Funktionsreihenfolge

Code: Alles auswählen

int lang = specificLanguageString.toInt();
int num = specificNumberString.toInt();
query.exec( QString( "INSERT INTO T_Text ([Language], [No] , [Text])  VALUES ( '%1', '%2', '%3' )" ).arg(lang).arg(num).arg(specificText) );
macman
Beiträge: 1738
Registriert: 15. Juni 2005 13:33
Wohnort: Gütersloh
Kontaktdaten:

Beitrag von macman »

Hast Du es schon mit dem gleichen String in Qt probiert, also ohne die Platzhalter, direkt feste Werte? Dann lass mal bei den Zahlenwerten die Hochkomma weg.
Die deutsche Schriftsprache ist case-sensitive. Außerdem gibt es eine Interpunktionsnorm. Wenn manch einer seine Programme genauso schlampig schreibt, wie sein Posting hier, dann sollte er es lieber bleiben lassen.
Antworten