Autor Beitrag
Shorti
Hält's aus hier
Beiträge: 10



BeitragVerfasst: Di 14.09.10 17:28 
Hallo zusammen,

ich bin dabei mir eine Funktion zu schreiben, mit der man innerhalb einer Firebird-Datenbank einen Datensatz duplizieren kann. Funktioniert soweit auch. Nur wenn ich danach die erste Spalte neu durchnummerieren will, wird die neue Nr. vom duplizierten Datensatz nicht in die Datenbank übernommen. Ich finde einfach den Fehler nicht, bitte helft mir.


Hier der 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:
procedure DatensatzDuplizieren(Query:TZQuery;Tabelle,SQLFilter:String);
var i : Integer;
    a : Integer;
    b : Integer;
    s : String;
    s1: String;
begin
  if (Query.FieldByName('Rangfolge').AsString <> ''then begin
    if (Query.FieldByName('Rangfolge').AsInteger >= 1then begin
      s1:= '';
      i := Query.RecNo; //TabPos merken
      s := Query.FieldByName('Rangfolge').AsString;

      // Alle Spaltennamen in einen String holen
      for a := 1 to Query.FieldCount - 1 do begin
        s1 := s1 + Query.Fields[a].FieldName + ',';
      end;
      Delete(s1,Length(s1),1);
      QueryExec(Query,'INSERT INTO '+Tabelle+' ('+s1+') SELECT '+s1+' FROM '        //  <<--- Hier wird die Zeile
                      +Tabelle+' WHERE Rangfolge = '+s,False);                      //        ohne die Spalte Rangfolge
      QueryExec(Query,'SELECT '+SQLFilter+' FROM '+Tabelle,True);                   //        dupliziert, alles i.o.

      //Eingefügten Eintrag mit der Rangnummer von der Quelle versehen
      Query.Last;
      Query.Edit;
      Query.FieldByName('Rangfolge').AsString := s;                                 //  <<--- Spalte Rangfolge bekommt 
      Query.Post;                                                                   //        für Sortierung Quell-Nr
      QueryExec(Query,'SELECT '+SQLFilter+' FROM '+Tabelle+' ORDER BY Rangfolge',True);

      //Rangfolge Neu nummerieren
      Query.First;
      a := 0;
      while not Query.Eof do begin
        inc(a);
        Query.Edit;
        Query.FieldByName('Rangfolge').AsInteger := a;                             //  <<--- Hier wird neu nummeriert 
        Query.Post;                                                                //        noch ist alles gut 
        Query.Next;
      end;//while not Query.Eof do begin
      QueryExec(Query,'SELECT '+SQLFilter+' FROM '+Tabelle,True);                  //  <<--- Hier bemerkt man 
      Query.RecNo := i;                                                            //        das Dilemma s.u.  
    end;//if (Query.FieldByName('Rangfolge').AsInteger >= 1) then begin
  end;//if Query.FieldByName('Rangfolge').AsString <> '' then begin

end;


Nach dem Aufruf "QueryExec(Query,'SELECT '+SQLFilter+' FROM '+Tabelle,True);" der Tabelle sieht man, das Quell- und Zielzeile immer noch die selbe Nummer in Spalte "Rangfolge" stehen haben. Ich bin ratlos.

MfG Shorti
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1335
Erhaltene Danke: 118

Win 10
RIO, CE, Lazarus
BeitragVerfasst: Di 14.09.10 18:00 
Kann es sein dass das Feld "Rangfolge" Autoinc Ist? Warum kopierst du die "Rangfolge" nicht gleich mit allen anderen Feldern mit? Das hat doch den gleichen Effekt als wie wenn du es nachher machst, zudem vermeidest du Fehler.
Fehler in den Ausschnitt von Zeile 24 bis 27: Da hast du eine schöne Fehlerquelle drinne die zu Fehlern führt wenn mehrere leute zur gleichen Zeit damit Einträge duplizieren.

_________________
Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
Shorti Threadstarter
Hält's aus hier
Beiträge: 10



BeitragVerfasst: Mi 15.09.10 08:08 
Danke erstmal für die schnelle Reaktion.

Zitat:
Kann es sein dass das Feld "Rangfolge" Autoinc Ist?


Da ich noch nicht lange mit Datenbanken arbeite, musst du mir mal auf die Sprünge helfen. Wenn mit "Autoinc" ein automatisches hochzählen gemeint ist, kann ich ganz klar nein sagen.

Zitat:
Warum kopierst du die "Rangfolge" nicht gleich mit allen anderen Feldern mit?


Habe ich erst versucht, aber durch die Zeile 19/20 wurde eine Endlosschleife ausgelöst, da aus derselben Tabelle mit derselben Bedingung "WHERE Rangfolge = '+s" wahrscheinlich das gleiche eingefügt wurde.

Zitat:
Fehler in den Ausschnitt von Zeile 24 bis 27: Da hast du eine schöne Fehlerquelle drinne die zu Fehlern führt wenn mehrere leute zur gleichen Zeit damit Einträge duplizieren.


Wie würdest du so etwas lösen?


MfG Shorti
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: Mi 15.09.10 11:00 
Etwa in der Art ...
insert into Sort ([text],rangfolge) Select [Text],(Select max(rangfolge) + 1 from Sort) from Sort where rangfolge=10;
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: Mi 15.09.10 11:19 
einen hab ich noch zu resortieren, geht unter MSSQL
keine Ahnung ob Deine DB-Engine das unterstützt


Update Sort set Rangfolge=1 where Rangfolge = (Select min(Rangfolge) from Sort)
While (Select max(Rangfolge) from Sort)<>(Select Count(*) from Sort)
begin
update Sort set Rangfolge=(Select max(Rangfolge) + 1 from Sort s where s.Rangfolge<Sort.Rangfolge) where Rangfolge<>1
end
Shorti Threadstarter
Hält's aus hier
Beiträge: 10



BeitragVerfasst: Mi 15.09.10 14:28 
Hallo Bummi,

durch deine Anregung der Sortierung mit SQL, habe ich meine Strategie nochmal überdacht und siehe da, es hat sogar etwas gebracht. Der Code ist auch etwas kürzer geworden.

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:
procedure DatensatzDuplizieren(Query:TZQuery;Tabelle,SQLFilter:String);
var i : Integer;
    a : Integer;
    b : Integer;
    s : String;
    s1: String;
begin
  if (Query.FieldByName('Rangfolge').AsString <> ''then begin
    if (Query.FieldByName('Rangfolge').AsInteger >= 1then begin
      s1:= '';
      i := Query.RecNo; //TabPos merken
      s := Query.FieldByName('Rangfolge').AsString;

      // Alle Spaltennamen in einen String holen
      for a := 1 to Query.FieldCount - 1 do begin
        s1 := s1 + Query.Fields[a].FieldName + ',';
      end;
      Delete(s1,Length(s1),1);

      QueryExec(Query,'UPDATE '+Tabelle+' SET Rangfolge = Rangfolge + 1 WHERE Rangfolge > '+s,False);
      QueryExec(Query,'INSERT INTO '+Tabelle+' (Rangfolge,'+s1+
                      ') SELECT '+s+'+1,'+s1+
                      ' FROM '+Tabelle+' WHERE Rangfolge = '+s,False);
      QueryExec(Query,'SELECT '+SQLFilter+' FROM '+Tabelle+' ORDER BY Rangfolge',True);
      Query.RecNo := i;
    end;//if (Query.FieldByName('Rangfolge').AsInteger >= 1) then begin
  end;//if Query.FieldByName('Rangfolge').AsString <> '' then begin

end;


Vielen Dank nochmal dafür.

Aber wenn mir jetzt noch jemand erklären könnte, warum bei dem alten Code das Nummerieren der neu eingefügten Zeile nicht in die Datenbank übernommen wurde, wäre ich wunschlos glücklich. Das lässt mir keine Ruhe.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
      //Rangfolge Neu nummerieren
      Query.First;
      a := 0;
      while not Query.Eof do begin
        inc(a);
        Query.Edit;
        Query.FieldByName('Rangfolge').AsInteger := a;                             //  <<--- Hier wird neu nummeriert 
        Query.Post;                                                                //        noch ist alles gut 
        Query.Next;
      end;//while not Query.Eof do begin
      QueryExec(Query,'SELECT '+SQLFilter+' FROM '+Tabelle,True);                  //  <<--- Hier bemerkt man 
      Query.RecNo := i;                                                            //        das Dilemma s.u.


Nehmen wir mal an, es gibt Rangfolge 1-4. Ich markiere Nummer 2 und dupliziere mit "INSERT INTO", vergebe der Zeile vorläufig auch die Nummer 2 mit "Query.FieldByName('Rangfolge').AsInteger := 2;", Sortiere dann nach Rangfolge. Nun ist schonmal im Query alles in der richtigen Reihenfolge. Nun beginnt die Funktion wie oben zu sehen. Die Schleife funktioniert auch, es wird alles richtig nummeriert, aber nur im Query. Werden nun die Daten mit "QueryExec(..." neu aufgerufen, sieht man, das die neue Zeile immer noch die Nummer 2 hat. (Wie vorhin vergeben) WARUM???

MfG Shorti