Autor Beitrag
rs1305
Hält's aus hier
Beiträge: 7



BeitragVerfasst: Mo 07.09.15 15:41 
Hallo,

ich möchte einen Bereich aus einer Firebird Datenbank lesen, einen Wert verändern und dann wieder zurückschreiben. Hierzu soll folgender Code dienen:

Mydata ist vom Typ TIBDataset, alles andere ist auch richtig deklariert.

Leider bekomme ich den Fehler "eine Datenmenge die nur zum Lesen geöffnet ist, kann nicht geändert werden. Aber ich sehe hier keine Ursache, vermutlich nur
ein Verständnisproblem meinerseits (Delphi & Firebird sind Neuland für mich).

Es wäre super, wenn mir hier jemand helfen könnte - hab schon einen kompletten Tag mit diesem Problem verplempert.

Sorry - hatte was vergessen beim kopieren

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:
24:
25:
26:
27:
28:
29:
30:
Begin
  sqlmsg := 'SELECT * from arstamm where F019='''+Key+'''';
  mydata.Database := frmMain.oDB;
  mydata.Close;
  MyData.SelectSQL.Clear;
  myData.SelectSQL.Add(sqlmsg);
  mydata.Open;

  MyData.First;
  If Not mydata.IsEmpty Then Begin
      repeat;
         ArtikelNr := mydata.FieldByName('F001').Value;
         if ek_click then begin
            sourcevalue := mydata.FieldByName('F021').Value;
            destvalue := sourcevalue * prozent / 100;
            mydata.Edit;
            mydata.FieldByName('F021').AsFloat := destvalue;
            mydata.Post;
         end

         mydata.Next;

    until mydata.Eof;
  end;

  mydata.Close;
  Screen.Cursor := crDefault;
  oTa.CommitRetaining;

end;


Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt


Zuletzt bearbeitet von rs1305 am Mo 07.09.15 16:43, insgesamt 3-mal bearbeitet
haentschman
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 285
Erhaltene Danke: 33


DX10 Berlin Professional
BeitragVerfasst: Mo 07.09.15 16:01 
Hallöle... 8)
Zitat:
mydata.ExecSQL;

...kannst du mal erklären was du damit bezweckst?
Zitat:

if ek_click then begin
sourcevalue := mydata.FieldByName('F021').Value;
destvalue := sourcevalue * prozent / 100;
end;

:wink: als Zitat wegen der Markierungen. Was bedeuten die markierten Variablen?


Zuletzt bearbeitet von haentschman am Mo 07.09.15 16:04, insgesamt 1-mal bearbeitet
baumina
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 305
Erhaltene Danke: 61

Win 7
Delphi 10.2 Tokyo Enterprise
BeitragVerfasst: Mo 07.09.15 16:04 
Für einen select-Befehl in einem Dataset benutzt du Dataset.Open, um die Datenmenge zu erhalten. Ein ExecSQL macht man nur, wenn keine Datenmenge erwartet wird. Also lass das ExecSQL weg. Um eine geöffnete Datenmenge zu editieren, benutzt man Dataset.Edit, dann zum Ändern eines Feldes z.B. Dataset.FieldByName('[FeldName]').AsString := 'geändert'; und zum Speichern der Änderung Dataset.Post.
haentschman
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 285
Erhaltene Danke: 33


DX10 Berlin Professional
BeitragVerfasst: Mo 07.09.15 16:06 
:D Oben macht er ja ein Open. Die Inhalte werden irgendwelchen Variablen zugewiesen / berechnet. Das Ändern, so wie du es beschrieben hast, fehlt komplett.
rs1305 Threadstarter
Hält's aus hier
Beiträge: 7



BeitragVerfasst: Mo 07.09.15 16:40 
user profile iconhaentschman hat folgendes geschrieben Zum zitierten Posting springen:
Hallöle... 8)
Zitat:
mydata.ExecSQL;

...kannst du mal erklären was du damit bezweckst?
Zitat:

if ek_click then begin
sourcevalue := mydata.FieldByName('F021').Value;
destvalue := sourcevalue * prozent / 100;
end;

:wink: als Zitat wegen der Markierungen. Was bedeuten die markierten Variablen?


klar kann ich das ... ich lese eine Datenmenge, nehme ein Feld daraus und multipliziere es mit dem Faktor X (eine lineare Preiserhöhung) .. da kommen noch ein paar andere Sachen dazu, aber das ist jetzt unerheblich.
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 07.09.15 21:37 
user profile iconrs1305 hat folgendes geschrieben Zum zitierten Posting springen:
Leider bekomme ich den Fehler "eine Datenmenge die nur zum Lesen geöffnet ist, kann nicht geändert werden.

Diese Fehlermeldung sagt doch bereits alles, was für die Fehlerbehebung notwendig ist: Du versuchst, die Datenmende eines Dataset in die Datenbank zu schreiben, obwohl das Dataset nur zum Schreiben geöffnet wurde. Das kann zwei Ursachen haben:
  1. Es handelt sich um eine unidirektionale Komponente, die entweder nur lesen oder nur schreiben kann, nicht aber beides. Mit anderen Worten: Datenmengen unidirektionaler Datenbank-Komponenten (das sind zumeist die etwas älteren) können entweder zum Lesen oder zum Schreiben geöffnet werden, nicht aber für beides gleichzeitig.
  2. Das Property ReadOnly des Datasets wurde gesetzt.

Wenn du mit einer unidirektionalen Datenmenge arbeitest, kannst du also nicht dieselbe Datenmenge wieder zurückschreiben. Daher empfehle ich, im Datenmodul entsprechende Methoden bereitzustellen, die diese Aufgaben erledigen:

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:
24:
25:
26:
27:
28:
Function TDatenModul.GetAdresseByName(Const Nachname,Vorname : StringVar Id : Integer; Var Strasse,PLZ,Ort : String) : Boolean;
begin
  Try
    MyQuery.Active := False;
    MyQuery.SQL.Clear;
    MyQuery.SQL.Append('select * from ADRESSEN');
    MyQuery.SQL.Append('where NACHNAME = ' + QuotedStr(Nachname));
    MyQuery.SQL.Append('and   VORNAME  = ' + QuotedStr(Vorname));
    MyQuery.Open;
    Result := MyQuery.RecordCount > 0;
    If Result Then
    Begin
      Id      := MyQuery.FieldByName('STRASSE').AsInteger;
      Strasse := MyQuery.FieldByName('STRASSE').AsString;
      PLZ     := MyQuery.FieldByName('PLZ').AsString;
      Ort     := MyQuery.FieldByName('ORT').AsString;
    End Else
    Begin
      Id      := -1;
      Strasse := '';
      PLZ     := '';
      Ort     := '';
    End;
  Finally
    MyQuery.Active := False;
    MyQuery.SQL.Clear;
  End;
end;


Genauso erstellst du dir dann eine Methode, die das Dataset wieder zurückschreibt:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
Procedure TDatenModul.WriteAdresseToDB(Const Id : Integer; Nachname,Vorname,Strasse,PLZ,Ort : String);
begin
  Try
    MyQuery.Active := False;
    MyQuery.SQL.Clear;
    MyQuery.SQL.Append('update ADRESSEN set');
    MyQuery.SQL.Append('NACHNAME = ' + QuotedStr(Nachname) + ',');
    MyQuery.SQL.Append('VORNAME  = ' + QuotedStr(Vorname) + ',');
    MyQuery.SQL.Append('STRASSE  = ' + QuotedStr(Strasse) + ',');
    MyQuery.SQL.Append('PLZ      = ' + QuotedStr(PLZ) + ',');
    MyQuery.SQL.Append('ORT      = ' + QuotedStr(Ort));
    MyQuery.SQL.Append('where ID = ' + IntToStr(Id));
    MyQuery.ExecSQL;
  Finally
    MyQuery.SQL.Clear;
  End;
end;

Um das Erlernen wenigstens der grundlegendsten SQL-Befehle kommst du natürlich nicht herum, aber das macht einen Datenbank-Entwickler eben aus: er kennt sich (mehr oder weniger) auch in der entsprechenden Abfragesprache aus.

Code ist ungetestet, da nur schnell zur Veranschaulichung in den Editor getippt.