Probleme mit INSERT Befehl
-
Hallo
Ich habe ein Problem, und zwar gibt es mir nach folgendem Code immer diese Felhermeldung aus: "...[Microsoft][ODBC Mircosoft Access Driver] 1 Parameter wurden erwartet, aber es wurden zu wenig Parameter übergeben'..."
Ich habe folgendes:
Ich habe eine ADOConnection1 auf eine MSSQL Datenbank, diese funktioniert auch.
Denn ich lese mit ADOQuery1 die Daten aus dieser Datenbank in ein StringGrid.Nun lese ich gleich zeitig diese Daten von der ADOQuery1 in ein zweidimensionalen Array. Nun möchte ich diesen Array in eine MS Access Datenbank schreiben.
#include <vcl.h> #pragma hdrstop #include <string> #include "Unit1.h" //----------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; AnsiString ItemsCombo1; AnsiString ItemsCombo2; String arr_spalte[80]; AnsiString sqltext; String daten[1000][1000]; //----------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { //Komponenten ausbleden StringGrid1->Visible= false; } //----------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { //Sichtbarkeit der Elemente: StringGrid1->Visible = true; //Variablen deklarieren int j = 0; int datasize_tmp; int datasize; AnsiString tmp; AnsiString test; AnsiString Spalte; Form1->ADOQuery1->SQL->Text = "SELECT * FROM tabelle_kunde"; Form1->ADOQuery1->Open(); //StringGrid anhand der ADOQuery aufbauen (i = Spalten, j = Zeilen) for(ADOQuery1->First(); !ADOQuery1->Eof; ADOQuery1->Next()) { //Spaltenüberschriften auslesen und in oberste Zeile (J = [0]) schreiben for(int i = 0; i < ADOQuery1->Fields->Count; i++) { Spalte = ADOQuery1->Fields->Fields[i]->FieldName; StringGrid1->Cells[i][0] = Spalte; } //Felder aus der Datenbank lesen mit ADOQuery und in StringGrid schreiben for(int i = 0; i < ADOQuery1->Fields->Count; i++) { StringGrid1->Cells[i][j+1] = ADOQuery1->Fields->Fields[i]->AsString; StringGrid1->ColCount = i+1; } j++; StringGrid1->RowCount = j+1; } //----------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { ADOQuery2->ConnectionString = ADOConnection2->ConnectionString; int j = 0; int i = 0; int count; String mdbspalten[100]; for(ADOQuery1->First(); !ADOQuery1->Eof; ADOQuery1->Next()) { //Spaltenüberschriften auslesen for(int i = 0; i < ADOQuery1->Fields->Count; i++) { mdbspalten[i] = ADOQuery1->Fields->Fields[i]->FieldName; } //Daten aus ADOQuery 1 lesen und in Array schreiben: for(int i = 0; i < ADOQuery1->Fields->Count; i++) { daten[i][j] = ADOQuery1->Fields->Fields[i]->AsString; } //Daten aus dem Array daten lesen und per ADOQuery2 in Datenbank schreiben: for(int i = 0; i < ADOQuery1->Fields->Count; i++) { ADOQuery2->SQL->Clear(); ADOQuery2->SQL->Text = "INSERT INTO test (" + mdbspalten[i] + ") VALUES (" + daten[i][j] + ")"; ADOQuery2->Open(); } j++; } } //---------------------------------------------------------------------------hoffe ihr versteht mein code?
Ich habe bis jetzt herausgefunden dass dieser Fehler auftritt, wenn falsche Spaltennamen beim Insert-Befehl verwendet wurden, jedoch stimmen die Spaltennamen überein!!vielen dank für eine Antwort!

gruss
-
Bei solchen Fehlern liegt das Problem nur indirekt im Programm-Code! Viel spannender sind die generierten SQL-Anweisungen. Gib die mal als Strings aus! Wenn ich die Meldung richtig deute, stimmen die Anzahl der Spalten nicht mit der Anzahl der Values überein! Vielleicht ist Einer nicht initialisiert ?
Jedenfalls würde ich zunächst mal in den generierten SQL-Anweisungen suchen, was der SQL-Server vermißt!
-
ok, habe ich gemacht!
ein sql statement für einen datensatz sieht so aus:INSERT INTO test (source) VALUES (0007)INSERT INTO test (beam) VALUES (6)INSERT INTO test (alarm) VALUES (1)INSERT INTO test (alarm_no) VALUES (1103)INSERT INTO test (x) VALUES (0)INSERT INTO test
VALUES (0)INSERT INTO test (w) VALUES (0)INSERT INTO test (h) VALUES (0)INSERT INTO test (value) VALUES (0)INSERT INTO test (classes) VALUES (D)das wäre ein statement für einen einzigen datensatz, da die tabelle 10 spalten hat!
geht das überhaupt so?das für jede einzelnes feld im datensatz ein eigenes sql statement geschickt wird??
gruss
-
Hi,
ein INSERT-Statement bei SQL muss so aussehen:
INSERT INTO (SPALTE1, SPALTE2, SPALTE3) VALUES(WERT1, WERT2, WERT3)
Dabei muss man darauf achten, dass wenn z.b.Spalte1 ein Varchar ist, Wert1 mit einfachen '' umschlossen wird. Bei z.B. Integer-Spalten müssen die nicht verwendet werden.
Hoffentlich hilft das weiter

strauberry
-
heisst das, dass ich in einem sql statement gleich alle werte für alle spalten angeben muss??
-
Du musst nicht alle Spalten angeben. Es ist nur wichtig, dass die Menge der Spalten der Menge der Werte gleich ist.
Folgendes geht auch
INSERT INTO TABELLE (Spalte1, spalte22, spalte3) VALUES(.....)
Du hast nur einen Teil der Spalten (sogar Reihenfolge ist egal) angegeben, es funktioniert aber trotzdem. Es müssen halt in beiden Angaben die gleichen Spaltenmengen drinstehen...
-
hmm, dann sollte es ja so funktionieren, oder net?
ich frage mich nun gerade, ob ich nicht auch noch eine for schleife brache für das ADOQuery2?? for(ADOQuery2->First(); !ADOQuery2->Eof; ADOQuery2->Next())??
sonst springt er ja nicht zum nächsten datensatz in der tabelle, in welche ich schreibe??
-
Sind das bei dir alles Int TinyInt ... spalten?
-
es ist eine microsoft access datenbank, ich habe in der tabelle mal alle spalten auf den datentyp "text" gestellt, man kann da zahlen, text reinschreiben!also an dem sollte es eigentlich nicht liegen
-
Kann man das in Access irgendwie ausprobieren?
das wäre ein statement für einen einzigen datensatz, da die tabelle 10 spalten hat!
Stimmt so nicht ganz... mit jedem Insert wird ein neuer Datensatz erzeugt (Nur so am Rande)
-
Wenn alles Textfelder sind, lautet das Zauberwort wohl QuotedString...
Grundsätzlích:
Solche 'zusammengebastelten' Befehle beeinträchtigen die Performance. Eine einmal erstellte Anweisung mit 'richtigen' Parametern wird vom Server vorbereitet (prepared). Danach werden nur noch die neuen Parameter übergeben. Bei Deiner vorgehensweise muss jede Ausführung erneut vom Server vorbereitet werden.Auch wenn das hier Access íst und somit kein Server vorhanden ist, sollte man sich über so was Gedanken machen. Insbesondere wenn vielleicht mal eine Umstellung auf eine echte SQL-Datenbank geplant ist.
-
könntest du mir sagen wie das mit diesem quotedstring funktioniert?
ich habe es mir nun mal einfach gemacht und folgendes probiert:ADOQuery2->SQL->Text =
"INSERT INTO test (source,beam,alarm_id,alarm_nr,x,y,w,h,value,classes)
VALUES ('as','ds','as','ser','aina','wil','lu','tschen','min','penu')";
ADOQuery2->Open();doch leider funktioniert nicht mal das?has auch mal noch probiert ohne die hochkommas (')!

gruss
-
QuotedString() ist eine String-Funktion und setzt einfach nur vor und hinter den eigentlichen String ein Anführungszeichen. Damit spartst Du Dir das manuelle Einfügen der Anführungszeichen.
Ich würde trotzdem eine parametrisierte SQL-Anweisung verwenden. Also eine feste SQL-Anweisung, der Parameter übergeben werden müssen. Da brauchst Du dann auch kein QuotedString...
-
trade schrieb:
ein sql statement für einen datensatz sieht so aus:
INSERT INTO test (source) VALUES (0007)INSERT INTO test (beam) VALUES (6)INSERT INTO test (alarm) VALUES (1)INSERT INTO test (alarm_no) VALUES (1103)INSERT INTO test (x) VALUES (0)INSERT INTO test
VALUES (0)INSERT INTO test (w) VALUES (0)INSERT INTO test (h) VALUES (0)INSERT INTO test (value) VALUES (0)INSERT INTO test (classes) VALUES (D)das wäre ein statement für einen einzigen datensatz, da die tabelle 10 spalten hat!
geht das überhaupt so?das für jede einzelnes feld im datensatz ein eigenes sql statement geschickt wird??damit schreibst du nicht EINEN Datensatz sondern 10, da jeder Insert-Befehl einen Datensatz anlegt
also entweder machst du das Insert für alle Spalten auf einmal oder du mußt nach dem ersten Insert für alle weiteren Daten des Datensatzes Update verwenden
außerdem könnte helfen wenn du VOR dem Löschen des SQL-Statments des Query wieder schließen tust, z.B.
//Daten aus dem Array daten lesen und per ADOQuery2 in Datenbank schreiben: for(int i = 0; i < ADOQuery1->Fields->Count; i++) { ADOQuery2->Close(); ADOQuery2->SQL->Clear(); ADOQuery2->SQL->Add("INSERT INTO test (" + mdbspalten[i] + ") VALUES (" + daten[i][j] + ")"); ADOQuery2->Open(); }ADOQuery2->SQL->Text =
"INSERT INTO test (source,beam,alarm_id,alarm_nr,x,y,w,h,value,classes)
VALUES ('as','ds','as','ser','aina','wil','lu','tschen','min','penu')";
ADOQuery2->Open();doch leider funktioniert nicht mal das?has auch mal noch probiert ohne die hochkommas (')!
sind deine Felder wirklich alle vom Typ String? oder verlangen z.B. x,y und h nicht vielleicht Zahlen?
Grüße
Linnea