Autor Beitrag
SIJAS
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Mi 25.07.07 15:57 
Hallo Delphiforum,

ich bin leider absoluter Neuling im Umgang mit ADO-Komponenten und SQL Befehlen.

Nun habe ich ein Problem mit dem folgenden Code:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
AdoQuery6.SQL.Clear;  //Querys werden gelöscht
AdoQuery5.SQL.Clear;

AdoQuery5.Close;           //ADOQuery5 holt Daten aus der Datenbank aufgrund von Userangaben
AdoQuery5.Active:=false;
AdoQuery5.SQL.Add('Select ID,Telephone,TelephoneType,AnswerSMS,UserLanguage FROM PersonalData_DB where ID = '+dbgrid3.SelectedField.Text);
AdoQuery5.ExecSQL;

AdoQuery5.DisableControls;   //Controls werden ausgeschalten um die Performance während der      
AdoQuery6.DisableControls;   //Schleife zu erhöhen
adodataset1.DisableControls;
adodataset2.DisableControls;

AdoQuery5.First;
while not AdoQuery5.Eof do              //Schleife durch alle Datensätze von AdoQuery5
begin
  buffer1:= AdoQuery5.Fields[0].AsString;         // Felder auswerten ~
  buffer2:= AdoQuery5.Fields[1].AsString;
  buffer3:= AdoQuery5.Fields[2].AsString;
  buffer4:= AdoQuery5.Fields[3].AsString;
  buffer5:= AdoQuery5.Fields[4].AsString;

  AdoQuery6.SQL.Clear;
  AdoQuery6.Active:=false;


  QueryString:='INSERT INTO Puffer3([ID]) VALUES("'+buffer1+'")'//Id wird in Puffer3 geschrieben
  AdoQuery6.SQL.Add(QueryString);
  AdoQuery6.ExecSQL;



   AdoQuery6.SQL.Clear;       //Alle Daten werden in Puffer6 geschrieben
   AdoQuery6.Active:=false;
   AdoQuery6.SQL.Add('INSERT INTO Puffer6 (ID,Telephone,TelephoneType,AnswerSMS,Userlanguage) VALUES ("'+buffer1+'","'+buffer2+'","'+buffer3+'","'+buffer4+'","'+buffer5+'")');
   AdoQuery6.ExecSQL;


  AdoQuery5.Next;
end;

AdoQuery5.Close;
AdoQuery6.Close;    //Querys werden geschlossen

adodataset1.EnableControls;  //Controls wieder einschalten
adodataset2.EnableControls;
adoquery5.EnableControls;
adoquery6.EnableControls;


//sleep(1000);    //Mit diesem sleep-Befehl funktioniert die folgende Abfrage problemlos nur mit 
                  //lästiger Verzögerung


  AdoQuery9.Active:=false;   //Alle Datensätze aus Puffer6 in einem DB-Grid anzeigen
  AdoQuery9.SQL.Clear;
  AdoQuery9.SQL.Add('SELECT * FROM Puffer6');
  AdoQuery9.Active:=true;
  AdoQuery9.Open;             //Hier wird meist der letzte Datensatz von AdoQuery6 nicht angezeigt


Mein Problem ist das ich mit ADOQuery5 einen ID-Eintrag suche (später sollen es mehrere werden deshalb die EOF-Schleife) und diesen/diese dann mit ADOQuery6 in eine Access-Datenbank in eine Tabelle "Puffer6" schreibe.

Soweit klappt das ganze schon problemlos. Das Problem ist das ich anschließend alle Daten aus "Puffer6" mit AdoQuery9 wieder auslese um die Tabelle in einem DB-Grid anzuzeigen. Hierbei scheint jedoch ADOQuery6 die Schreib-Operation noch nicht abgeschlossen zu haben da es sich immer so verhält das der letzte Eintrag der mit ADOQuery6 geschrieben wurde nicht im ADOQuery9-DBGrid angezeigt wird.

Wenn ich mir jedoch die Datenbank direkt mit Access ansehe ist dort der Datenbankeintrag geschrieben worden. Wenn ich den Sleep(1000) Befehl einkommentiere funktioniert es ohne Probleme nur finde ich diese Lösung nicht akzeptabel.

Gibt es eine andere Möglichkeit um auf das Ende des vorherigen SQL-Befehls zu warten oder um zu prüfen wann dieser beendet ist?

Ich hoffe ich habe alle wichtigen Informationen für mein Problem gepostet und das mir jemand hierbei helfen kann. Auch für andere Tipps zu Optimierung des Codes wäre ich dankbar.

Grüße Euer Sijas

Moderiert von user profile iconKlabautermann: Code- durch Delphi-Tags ersetzt
Agawain
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 460

win xp
D5, MySQL, devxpress
BeitragVerfasst: Mi 25.07.07 21:35 
hi

nene...also, ob ADO oder nicht ADO...folgendes gilt es zu beherzigen

Vor Veränderungen von Parametern, oder dem Statement die Tabelle schließen...Sieht man auch, wenn man im OI den SQL-Text ändert, die IDE setzt die Tabelle gnadenlos auf Active := false

also

Close
Clear
Add

Klar?

Dann
Active und Open haben ansich die gleich Wirkung

Open verwendet man, wenn, wenn man eine Rückgabemenge erwartet, also bei einem SELECT * FROM... z.B.

ExecSQL verwendet man, wenn man keine Rückgabemenge erwartet, z.B. bei UPDATE, DELETE, INSERT

Überarbeite das Ganze mal nach den von mir genannten Anmerkungen, mach auch ruhig Gebrauch von der F1-Taste, dann sehen wir weiter

Gruß

Aga
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Mi 25.07.07 22:56 
Mein Senf:

1. Gib den ADOQueries sinnvolle Namen. dsAdressen (ds=DataSet) ist lesbarer als ADOQuery5.
2. Verwende persistente Felder. Hä? Doppelklick auf die Query, 'Alle Felder hinzufügen' und dann kannst Du auf z.B. den Namen der Adresse direkt mit dsAdressenName.AsString zugreifen. Auch lesbarer.

_________________
Na denn, dann. Bis dann, denn.
raiguen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 374

WIN 2000prof, WIN XP prof
D7EP, MSSQL, ABSDB
BeitragVerfasst: Do 26.07.07 11:00 
Aus meiner Sicht gibt es zwei Optimierungsmöglichkeiten:

Schleife mit parametrisierten Queries
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
//--Queries vorbereiten, sofern noch nicht geschehen
if not ADOQuery5.Prepared then
  begin
    ADOQuery5.Close;
    ADOQuery5.SQL.Text := 'SELECT ID,Telephone,TelephoneType,AnswerSMS,UserLanguage ' +
                          'FROM PersonalData_DB where ID = :ID ';
    ADOQuery5.Prepared := true;
 end;

if not ADOQuery6_1.Prepared then     //Id wird in Puffer3 geschrieben
  begin
    ADOQuery6_1.Close;
    ADOQuery6_1.SQL.Text := 'INSERT INTO Puffer3([ID]) VALUES(:buffer1)';
    ADOQuery6_1.Prepare;
end;

if not ADOQuery6_2.Prepared then     //Alle Daten werden in Puffer6 geschrieben
  begin
    ADOQuery6_2.Close;
    ADOQuery6_2.SQL.Text := 'INSERT INTO Puffer6 (ID,Telephone,TelephoneType,AnswerSMS,Userlanguage) ' +
                            'VALUES (:buffer1, :buffer2, :buffer3, :buffer4, :buffer5');
    ADOQuery6_2.Prepare;
end;

AdoQuery5.DisableControls;   //Controls werden ausgeschalten um die Performance während der      
AdoQuery6.DisableControls;   //Schleife zu erhöhen


//--Parameter übergeben und Query ausführen
ADOQuery5.Close;
ADOQuery5.ParamByName('ID').AsString := dbgrid3.SelectedField.Text;
ADOQuery5.Open;


while not AdoQuery5.Eof do              //Schleife durch alle Datensätze von AdoQuery5
begin
  buffer1:= AdoQuery5.Fields[0].AsString;         
  buffer2:= AdoQuery5.Fields[1].AsString;
  buffer3:= AdoQuery5.Fields[2].AsString;
  buffer4:= AdoQuery5.Fields[3].AsString;
  buffer5:= AdoQuery5.Fields[4].AsString;

  //--zur besseren Lesbarkeit - 
{
  buffer1:= AdoQuery5.FieldByName('ID').AsString;         
  buffer2:= AdoQuery5.FieldByName('Telephone').AsString;
  buffer3:= AdoQuery5.FieldByName('TelephoneType').AsString;
  buffer4:= AdoQuery5.FieldByName('AnswerSMS').AsString;
  buffer5:= AdoQuery5.FieldByName('UserLanguage').AsString;
}


  //--Parameter setzen
  ADOQuery6_1.ParamByName('buffer1').AsString := buffer1;

  ADOQuery6_2.ParamByName('buffer1').AsString := buffer1;
  ADOQuery6_2.ParamByName('buffer2').AsString := buffer2;
  ADOQuery6_2.ParamByName('buffer3').AsString := buffer3;
  ADOQuery6_2.ParamByName('buffer4').AsString := buffer4;
  ADOQuery6_2.ParamByName('buffer5').AsString := buffer5;

  //--ausführen
  ADOQuery6_1.ExecSQL;
  ADOQuery6_2.ExecSQL;

  AdoQuery5.Next;
end;

AdoQuery5.Close;

//Controls wieder einschalten
adoquery5.EnableControls;
adoquery6.EnableControls;

//--kann auch schon vorbereitet werden
if not ADOQuery9.Prepared then
  begin
    AdoQuery9.Close;   //Alle Datensätze aus Puffer6 in einem DB-Grid anzeigen
    AdoQuery9.SQL.Text := 'SELECT * FROM Puffer6';
    AdoQuery9.Prepare;
end;

AdoQuery9.Open;

Das ständige Neuerstellen eines SQL-Statements kostet Zeit (Speicher belegen, Statement parsen und ausführen, Speicher wieder freigeben);
besser ist es daher, dieses mit Parametern vorzubereiten und anschliessend die entsprechenden Parameter zu setzen.

Was weiterhin Zeit kostet, ist das Einfügen von Datensätzen mittels einer Schleife. Hierzu gibt es (hoffentlich bei ADO auch??) eine
elegantere Möglichkeit
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
//--Queries vorbereiten, sofern noch nicht geschehen
if not ADOQuery6_1.Prepared then     //Id wird in Puffer3 geschrieben
  begin
    ADOQuery6_1.Close;
    ADOQuery6_1.SQL.Text := 'INSERT INTO Puffer3 ([ID]) ' +
                            'SELECT ID FROM PersonalData_DB WHERE ID = :ID ';
    ADOQuery6_1.Prepare;
end;

if not ADOQuery6_2.Prepared then     //--Alle Daten werden in Puffer6 geschrieben
  begin
    ADOQuery6_2.Close;
    ADOQuery6_2.SQL.Text := 'INSERT INTO Puffer6 (ID,Telephone,TelephoneType,AnswerSMS,Userlanguage) ' +
                            'SELECT ID,Telephone,TelephoneType,AnswerSMS,UserLanguage ' +
                            'FROM PersonalData_DB where ID = :ID ';
    ADOQuery6_2.Prepare;
end;

//--Parameter setzen und ausführen
ADOQuery6_1.ParamByName('ID').AsString := dbgrid3.SelectedField.Text;
ADOQuery6_1.ExecSQL;
ADOQuery6_2.ParamByName('ID').AsString := dbgrid3.SelectedField.Text;
ADOQuery6_2.ExecSQL;

Ich habe erstmal bewusst deine wenig aussagekräftigen Query-Benamung genommen, um den Optimierungsweg aufzuzeigen.
Selbstverständlich solltest du wegen der besserne Lesbarkeit/Wartbarkeit den Queries einen klingenden Namen verpassen ;)
SIJAS Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Do 26.07.07 14:00 
Vielen Dank für die schnelle Hilfe. :D
Ich werd versuchen das so umzusetzen und meine Fortschritte dann hier posten.

Auch das mit den Querybezeichnungen werd ich in Zukunft beherzigen! :idea:
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: Do 26.07.07 14:45 
user profile iconalzaimar hat folgendes geschrieben:
2. Verwende persistente Felder. Hä? Doppelklick auf die Query, 'Alle Felder hinzufügen' und dann kannst Du auf z.B. den Namen der Adresse direkt mit dsAdressenName.AsString zugreifen. Auch lesbarer.

Schöner finde ich FieldByName mindestens genau so lesbar funktioniert aber auch bei Dynamisch erzeugten oder multifunktionalen Table/Querry Objekten.

Also einfach MyTable.FieldByName('MyField').AsString; ;).

Für user profile iconSIJAS vielleicht in dem Zusammenhang auch nützlich: www.delphi-library.d...ry+Arbeiten_363.html

Gruß
Klabautermann
SIJAS Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Do 26.07.07 16:29 
Nochmals danke für die vielen Tipps. :D
Ich bin gerade dabei das ganze nach raiguens Vorschlag zu gestalten, jedoch habe ich jetzt folgendes Problem:

Wenn ich den Parametern für die beiden Querys jetzt Werte zuweisen will, bekomme ich die Fehlermeldung:
"Parameter 'Param1' wurde nicht gefunden".

Habe daraufhin versucht die Parameter über CreateParameter und ADDParameter anzulegen aber meldet immer noch das die Paramter unbekannt sind. Wo mache ich hier noch einen Fehler?

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
if not Query_WritetoPuffer3.Prepared then     //Query für Puffer3 vorbereiten
  begin  
    Query_WritetoPuffer3.Close;
    Query_WritetoPuffer3.SQL.Clear;
    Query_WritetoPuffer6.Parameters.CreateParameter('Param1',ftUnknown,pdUnknown,255,'');
{    with Query_WritetoPuffer3.Parameters.AddParameter do
    begin
      DataType := ftUnknown;
      Name:='Param';
      Direction:=pdUnknown;
    end;   }

    Query_WritetoPuffer3.SQL.Text := 'INSERT INTO Puffer3 ([ID]) ' +
                            'SELECT ID FROM PersonalData_DB WHERE ID = :Param1 ';
    Query_WritetoPuffer3.ParamCheck:=true;
    Query_WritetoPuffer3.Prepared:=true;

end;


if not Query_WritetoPuffer6.Prepared then     //Query für Puffer6 vorbereiten
  begin
    Query_WritetoPuffer6.Close;
    Query_WritetoPuffer6.SQL.Clear;
    Query_WritetoPuffer6.Parameters.CreateParameter('Param2',ftUnknown,pdUnknown,255,'');
 {   with Query_WritetoPuffer6.Parameters.AddParameter do
    begin
      DataType := ftUnknown;
      Name:='Param2';
      Direction:=pdUnknown;
    end;}

    Query_WritetoPuffer6.SQL.Text := 'INSERT INTO Puffer6 (ID,Telephone,TelephoneType,AnswerSMS,Userlanguage) ' +
                            'SELECT ID,Telephone,TelephoneType,AnswerSMS,UserLanguage ' +
                            'FROM PersonalData_DB where ID = :Param2 ';
   Query_WritetoPuffer6.ParamCheck:=true;
   Query_WritetoPuffer6.Prepared:=true;
end;

Query_WritetoPuffer3.Parameters.GetParamList(Listending,'Param');

//--Parameter setzen und ausführen
Query_WritetoPuffer3.Parameters.ParamByName('Param1').Value := dbgrid3.SelectedField.Text;  //Hier tritt der Fehler auf!
Query_WritetoPuffer3.ExecSQL;
Query_WritetoPuffer6.Parameters.ParamByName('Param2').Value := dbgrid3.SelectedField.Text;
Query_WritetoPuffer6.ExecSQL;

  Query_Anzeige.Close;
  Query_Anzeige.SQL.Clear;
  Query_Anzeige.SQL.Add('SELECT * FROM Puffer6');
  Query_Anzeige.Open;
raiguen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 374

WIN 2000prof, WIN XP prof
D7EP, MSSQL, ABSDB
BeitragVerfasst: Fr 27.07.07 12:13 
Hi :) Sofern du den Fehler noch nicht gefunden hast, hier noch einige Hinweise:

user profile iconSIJAS hat folgendes geschrieben:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
if not Query_WritetoPuffer3.Prepared then     //Query für Puffer3 vorbereiten
  begin  
    Query_WritetoPuffer3.Close;
    Query_WritetoPuffer3.SQL.Clear;
    Query_WritetoPuffer6.Parameters.CreateParameter('Param1',ftUnknown,pdUnknown,255,'');
...
Das dürfte schon die erste Fehlerquelle sein...

user profile iconSIJAS hat folgendes geschrieben:
ausblenden Delphi-Quelltext
1:
2:
...
Query_WritetoPuffer3.Parameters.GetParamList(Listending,'Param');

Hier müsste es eigentlich auch knallen, da der Parameter mit Namen 'Param' nicht gefunden wird...
Wenn, dann müsste hier Param1 als 'Such'-Kriterium rein...

Warum eigentlich so 'kompliziert' ?? CreateParameter etc kannst du dir schenken, da die Parameterliste automatisch zur Laufzeit erzeugt wird, sobald sich das SQL-Statement ändert bzw neu erstellt wird. Somit kannst du dann bequem mittels ... .Parameters.ParamByName().Value bzw .Parameters[n].Value die entsprechenden Parameterwerte setzen:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
if not Query_WritetoPuffer3.Prepared then     //Query für Puffer3 vorbereiten
  begin  
    Query_WritetoPuffer3.Close;
    Query_WritetoPuffer3.SQL.Text := 'INSERT INTO Puffer3 ([ID]) ' +
                            'SELECT ID FROM PersonalData_DB WHERE ID = :Param1 ';
    Query_WritetoPuffer3.ParamCheck:=true;   //ist standardmässig schon true
    Query_WritetoPuffer3.Prepared:=true;
end;

if not Query_WritetoPuffer6.Prepared then     //Query für Puffer6 vorbereiten
  begin
    Query_WritetoPuffer6.Close;
    Query_WritetoPuffer6.SQL.Text := 'INSERT INTO Puffer6 (ID,Telephone,TelephoneType,AnswerSMS,Userlanguage) ' +
                            'SELECT ID,Telephone,TelephoneType,AnswerSMS,UserLanguage ' +
                            'FROM PersonalData_DB where ID = :Param2 ';
   Query_WritetoPuffer6.ParamCheck:=true;
   Query_WritetoPuffer6.Prepared:=true;
end;

//--Parameter setzen und ausführen
Query_WritetoPuffer3.Parameters.ParamByName('Param1').Value := dbgrid3.SelectedField.Text; 
//-- oder
Query_WritetoPuffer3.Parameters[0].Value := dbgrid3.SelectedField.Text; 
Query_WritetoPuffer3.ExecSQL;

Query_WritetoPuffer6.Parameters.ParamByName('Param2').Value := dbgrid3.SelectedField.Text;
//-- oder
Query_WritetoPuffer6.Parameters[0].Value := dbgrid3.SelectedField.Text;
Query_WritetoPuffer6.ExecSQL;

//--wird Query_Anzeige ausschliesslich hier verwendet? dann kann diese auch schon vorbereitet werden!
if not Query_Anzeige.Prepared then begin
  Query_Anzeige.Close;
  Query_Anzeige.SQL.Clear;
  Query_Anzeige.SQL.Add('SELECT * FROM Puffer6');
  Query_Anzeige.Prepared := true;
end;
  Query_Anzeige.Open;
SIJAS Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Mo 30.07.07 08:38 
Nochmals Danke für deine Hilfe raiguen!

Tut mir leid die beiden Fehler hab ich wohl eingebaut als ich versuchthab das zu lösen :oops:

habe jetzt den Quellcode genau so kopiert wie in deinem Post aber es scheitert immer noch an:

ausblenden Delphi-Quelltext
1:
Query_WritetoPuffer3.Parameters.ParamByName('Param1').Value := dbgrid3.SelectedField.Text;					


Der Parameter 'Param1' ist unbekannt. Ist die Fehlermeldung.

Auch über den Parameterindex kann ich nicht darauf zugreifen. Ist da noch irgend eine Einstellung an der ADO-Komponente falsch?
raiguen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 374

WIN 2000prof, WIN XP prof
D7EP, MSSQL, ABSDB
BeitragVerfasst: Di 31.07.07 09:27 
hmm... :gruebel: ... eigentlich dürfte die Fehlermeldung nicht kommen, da an den ADO_kompos nix grossartiges zu Schrauben(=Einstellen) gibt...Habe zum Test auch nur die ADO-Query-Kompo aufs Formular gezogen und keine Einstellungen (ausser dem Connesction-String natürlich)vorgenommen...
SIJAS Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Mi 08.08.07 10:59 
tja das mit den Parametern in den ADO-Query funktioniert irgendwie immer noch nicht aber mein Ursprüngliches Problem wurde ja gelöst.

Ich möchte mich nochmals bei allen bedanken die mir weitergeholfen haben! 8)