Delphi-PRAXiS
Seite 5 von 5   « Erste     345   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Schnellste Insert Möglichkeit für eine DB? (https://www.delphipraxis.net/148461-schnellste-insert-moeglichkeit-fuer-eine-db.html)

p80286 8. Mär 2010 14:21

Re: Schnellste Insert Möglichkeit für eine DB?
 
Zitat:

Zitat von xZise
Nun ist das aktuell so, dass jeder ein Flag bekommt, ob er in der Liste ist und standard ist das keiner. Dann geht er jede Person auf der Liste durch und vergleicht das mit der Datenbankliste und setzt das Flag auf „vorhanden“. Wenn das nicht der Fall ist, wird die Person hinzufügt. Kann ich jetzt zu Anfang ein SQL Befehl erstellen (präventiv) und das dann nutzen, auch wenn zwischenzeitlich mal ein Update kommt?
Ich benutze SQLite, und hoffe mal, dass ich nicht geschlagen werde, dass ich keinen neuen Thread auf mache :)

MfG
Fabian

hat die "Schülerliste" in der DB kein Ausgeschieden Datum/Flag was auch immer?

Um wieviele Datensätze geht es?
Ich würde es so machen, (in der DB) alle Schüler auf ausgeschieden setzen, Schüler aus Liste in DB suchen, Falls vorhanden Ausgeschieden zurück setzen, falls nicht vorhanden eintragen.
(ähnlich mach ich es mit den Personen die ich verwalten darf (ca 3.000 Laufzeit ca 1Min) extra Server/oracle)

Diese Listen "Wer nicht vorhanden ist den gibt's nicht mehr" sind natürlich sehr fehleranfällig, es wäre besser wenn es zu jedem Namen so etwas wie eine Arbeitsanweisung gäbe (neu anlegen / löschen / auf vorhanden sein prüfen)

Gruß
K-H

xZise 8. Mär 2010 15:02

Re: Schnellste Insert Möglichkeit für eine DB?
 
Moin,
genauso machen wir das ja auch im Moment. Und natürlich ist das Fehleranfällig, wenn man aber nur die Listen bekommt, wer alles ander Schule ist, dann kann man da nicht sehr viel anderes machen. Einzig, man könnte alle Schüler zum Schluss anzeigen, die gelöscht werden sollen.

Aber naja es ist eben nicht nur eine Personenliste, weshalb aktuell Personen ohne Klasse nicht existieren können.

Aber meine Frage ist halt, ob man quasi ganz am Anfang ein Query erstellen kann, auch wenn zwischenzeitlich andere Anweisungen durchgeführt werden. Wobei man könnte sogar mehrere Queries benutzen. Einmal ein „Schülerhinzufügen“-Query und ein „Schülervorhanden“-Query.

MfG
Fabian

PS: Es geht ingesamt nur um 1000 Schüler(innen).

p80286 8. Mär 2010 15:31

Re: Schnellste Insert Möglichkeit für eine DB?
 
Zitat:

Zitat von xZise
Aber naja es ist eben nicht nur eine Personenliste, weshalb aktuell Personen ohne Klasse nicht existieren können.

Das geht nicht????

Zitat:

Zitat von xZise
Aber meine Frage ist halt, ob man quasi ganz am Anfang ein Query erstellen kann, auch wenn zwischenzeitlich andere Anweisungen durchgeführt werden. Wobei man könnte sogar mehrere Queries benutzen. Einmal ein „Schülerhinzufügen“-Query und ein „Schülervorhanden“-Query.

Na klar kann man das, aber weil man das jederzeit kann, hab ich Deine Frage wohl nicht richtig verstanden.
Streng genommen gibt es keine "Schülerhinzufügen"-Abfrage nur eine Einfügen-Anweisung. Könntest Du vllt etwas Pseudo-Code produzieren?

Gruß
K-H

xZise 8. Mär 2010 15:58

Re: Schnellste Insert Möglichkeit für eine DB?
 
Moin,
naja es ist schon etwas her (6 Monate) und habe nicht mehr die genauen Spezifikationen vor Augen, aber das Problem ist, dass jede Person einen sogenannten Hauptkurs hat. Dieser Hauptkurs ist entweder ungültig und definiert damit einen Lehrer oder eben ein Schüler, dafür muss es aber ein Hauptkurs geben.
Ich habe demnächst wieder eine 6 Stunden Zugfahrt vor mir, wo ich mir evtl. das mal anschaue!

Aber die Frage die sich mir stellt, ist halt ob ich zwei Queries parallel laufen haben kann.

Und Pseudocode, öhrm, ich hoffe der Code ist soweit selbst erklärend:
Delphi-Quellcode:
procedure TDatenbankStationBasis.SchuelerEinlesen(const sDateiname: string);
const
  ANZAHL_ERSTER_SCHRITTE = 11;
var
  oExcel : TExcelApplication;
  oWorkbook : _WorkBook;
  oWorksheet : _WorkSheet;
  cLCID : Cardinal;
  i, j, iLehrerID, iJahrgang, iSchuelerAnzahl, iPersonenID : Integer;
  sKlasse, sKlassenlehrer, sName, sVorname : string;
  ILLehrerIDs, ILKursIDs, ILSchuelerIDs : TIntegerList;
  SLLehrerNachnamen, SLKursNamen, SLSchuelerNamen, SLSchuelerVornamen, SLSchuelerNachnamen : TStrings;
  ILPersonenIDs: TIntegerList;
  ILExemplarIDs: TIntegerList;
  i_cAnzahlSchritte: Integer;
  iAktuellerSchritt, iUeberAllesSchritt : Integer;
  iKursID: Integer;
begin
  oExcel := TExcelApplication.Create(nil);

  ILLehrerIDs := TIntegerList.Create;
  ILKursIDs := TIntegerList.Create;
  ILSchuelerIDs := TIntegerList.Create;
  ILPersonenIDs := TIntegerList.Create;
  ILExemplarIDs := TIntegerList.Create;

  SLLehrerNachnamen := TStringList.Create;
  SLSchuelerNamen := TStringList.Create;
  SLSchuelerVornamen := TStringList.Create;
  SLSchuelerNachnamen := TStringList.Create;
  SLKursNamen := TStringList.Create;
  try
    cLCID := GetUserDefaultLCID;

    oExcel.Connect;
    // Exceldatei laden
    try
      oWorkbook := oExcel.Workbooks.Open(sDateiname, emptyParam, true, emptyParam, emptyParam,
                          emptyParam, emptyParam, emptyParam, emptyParam, emptyParam, emptyParam,
                          emptyParam, emptyParam, emptyParam, emptyParam, cLCID);
    except
      on E : EOleSysError do
      begin
        raise EExcelNichtGefunden.CreateDef(e.Message);
      end;
    end;
    i_cAnzahlSchritte := oExcel.Worksheets.Count + 2;

    iAktuellerSchritt := 0;
    iUeberAllesSchritt := 0;

    // Alle LehrerIDs auslesen ...
    GeneriereDoppelFortschritt(i_cAnzahlSchritte, ANZAHL_ERSTER_SCHRITTE, iUeberAllesSchritt, iAktuellerSchritt, 'Einlesen starten', hstVorbereitung);
    GibLehrerIDs(ILLehrerIDs);
    GeneriereDoppelFortschritt(i_cAnzahlSchritte, ANZAHL_ERSTER_SCHRITTE, iUeberAllesSchritt, iAktuellerSchritt, 'LehrerIDs puffern', hstVorbereitung);

    // ... und dessen Nachnamen speichern
    GibNamenZuPIDL(SLLehrerNachnamen, ILLehrerIDs);
    ILLehrerIDs.IntegrateInStrings(SLLehrerNachnamen);
    GeneriereDoppelFortschritt(i_cAnzahlSchritte, ANZAHL_ERSTER_SCHRITTE, iUeberAllesSchritt, iAktuellerSchritt, 'Lehrer Nachnamen puffern', hstVorbereitung);

    // Dann die KursIDs einlesen ...
    GibKursIDs(ILKursIDs);
    GeneriereDoppelFortschritt(i_cAnzahlSchritte, ANZAHL_ERSTER_SCHRITTE, iUeberAllesSchritt, iAktuellerSchritt, 'Kurse puffern', hstVorbereitung);

    // ... und dessen Namen speichern
    GibKursnamenZuKIDL(SLKursNamen, ILKursIDs);
    GeneriereDoppelFortschritt(i_cAnzahlSchritte, ANZAHL_ERSTER_SCHRITTE, iUeberAllesSchritt, iAktuellerSchritt, 'Kursnamen puffern', hstVorbereitung);

    // Alle SchülerIDs einlesen ...
    GibSchuelerIDs(ILSchuelerIDs);
    GeneriereDoppelFortschritt(i_cAnzahlSchritte, ANZAHL_ERSTER_SCHRITTE, iUeberAllesSchritt, iAktuellerSchritt, 'Schüler puffern', hstVorbereitung);

    // ... und dessen Nachnamen speichern ...
    GibNamenZuPIDL(SLSchuelerNachnamen, ILSchuelerIDs);
    GeneriereDoppelFortschritt(i_cAnzahlSchritte, ANZAHL_ERSTER_SCHRITTE, iUeberAllesSchritt, iAktuellerSchritt, 'Schüler Nachnamen puffern', hstVorbereitung);

    // ... sowie dessen Vornamen ...
    GibVornamenZuPIDL(SLSchuelerVornamen, ILSchuelerIDs);
    GeneriereDoppelFortschritt(i_cAnzahlSchritte, ANZAHL_ERSTER_SCHRITTE, iUeberAllesSchritt, iAktuellerSchritt, 'Schüler Vornamen puffern', hstVorbereitung);

    // ... und diese dann kombinieren
    for j := 0 to SLSchuelerNachnamen.Count - 1 do
      SLSchuelerNamen.Add(SLSchuelerNachnamen[j] + '&' + SLSchuelerVornamen[j]);
    GeneriereDoppelFortschritt(i_cAnzahlSchritte, ANZAHL_ERSTER_SCHRITTE, iUeberAllesSchritt, iAktuellerSchritt, 'Schüler Namen puffern', hstVorbereitung);

    // Alle Kurse und Kurszuweisungen löschen, die nicht Hauptkurse sind
    EntferneZuSQL('Kurse', 'Hauptkurs <> 0');
    GeneriereDoppelFortschritt(i_cAnzahlSchritte, ANZAHL_ERSTER_SCHRITTE, iUeberAllesSchritt, iAktuellerSchritt, 'Kurse löschen', hstVorbereitung);
    EntferneZuSQL('Kurszuweisungen', 'KursID IN (SELECT KursID FROM Kurse WHERE Hauptkurs <> 0)');
    GeneriereDoppelFortschritt(i_cAnzahlSchritte, ANZAHL_ERSTER_SCHRITTE, iUeberAllesSchritt, iAktuellerSchritt, 'Kurszuweisungen löschen', hstVorbereitung);
    // Und dann die Schüler auf obsolet setzen
    ExecSQL('UPDATE Personen SET Obsolet = -1 WHERE HauptKursID != 0');
    GeneriereDoppelFortschritt(i_cAnzahlSchritte, ANZAHL_ERSTER_SCHRITTE, iUeberAllesSchritt, iAktuellerSchritt, 'Personen zum Löschen markieren', hstVorbereitung);

    BeginTransaction;
    for i := 1 to oExcel.Worksheets.Count do
    begin
      oWorksheet := oWorkbook.Sheets[i] as _WorkSheet;
      sKlasse := oWorksheet.Name;

      j := 1;
      while (CharInSet(sKlasse[j], ['0'..'9'])) and (j <= Length(sKlasse)) do
        Inc(j);
      iJahrgang := StrToIntDef(Copy(sKlasse, 1, j - 1), -1);

      // Lehrer einlesen (wenn der Name zu lang ist, ist der in der nächsten
      //  Zeile)
      sKlassenlehrer := oWorksheet.Cells.Item[2, 5].Value + oWorksheet.Cells.Item[3, 5].Value;
      // Anrede entfernen
      Delete(sKlassenlehrer, 1, 5);

      GeneriereDoppelFortschritt(i_cAnzahlSchritte, 1, iUeberAllesSchritt, iAktuellerSchritt, 'Tabelle/Klasse "' + sKlasse + '" wird eingelesen', hstEinlesen);

      if (iJahrgang >= 0) and (Length(sKlassenlehrer) > 0) then
      begin
        // Position des Nachnamens feststellen
        iLehrerID := SLLehrerNachnamen.IndexOf(sKlassenlehrer);
        // Lehrer existiert nicht
        if iLehrerID = -1 then
        begin
          // Dann nachfragen was geschehen soll
          if Assigned(fELF) then
            fELF(self, sKlassenlehrer, sKlasse, iLehrerID);

          if (iLehrerID = -1) or (not boIstLehrerZuPID(iLehrerID)) then
            raise ELehrerNichtGefunden.Create('Kein Lehrer zur Kurszuweisung gefunden.');
        end
        else //Lehrer vorhanden
        begin
          iLehrerID := Integer(SLLehrerNachnamen.Objects[iLehrerID]);
          ExecSQL('UPDATE Personen SET Obsolet = 0 WHERE PersonenID = '+ IntToStr(iLehrerID));
        end;

        // Gültige ID
        if iLehrerID > 0 then
        begin
          // Neuen Kurs anlegen
          iKursID := iFuegeKursHinzu(iJahrgang, iLehrerID, sKlasse, True);

          j := 10;
          while oWorksheet.Cells.Item[j, 2].Value <> '' do
          begin
            Inc(j);
          end;
          iSchuelerAnzahl := j - 10;

          if iSchuelerAnzahl = 0 then
            GeneriereDoppelFortschritt(i_cAnzahlSchritte, 1, iUeberAllesSchritt, iAktuellerSchritt, 'Klasse ' + sKlasse + ' eingelesen', hstEinlesen);
          for j := 0 to iSchuelerAnzahl - 1 do
          begin
            sName := oWorksheet.Cells.Item[j + 10, 2].Value;
            sVorname := sName;
            Delete(sName, Pos(',', sName), Length(sName) - Pos(',', sName)+1);
            Delete(sVorname, 1, Pos(',', sVorname) + 1);
            sName := Trim(sName);
            sVorname := Trim(sVorname);
            iPersonenID := ILSchuelerIDs.IntegersDef(SLSchuelerNamen.IndexOf(sName + '&' + sVorname), -1);
            // Überprüfen ob die PersonenID gültig ist
            if iPersonenID = -1 then
            begin
              iFuegeSchuelerHinzu(sName, sVorname, iKursID);
            end else
            begin
              WeiseHauptKursIDZuPIDZu(iPersonenID, iKursID);
            end;

            // Fortschritssbalken updaten
            GeneriereDoppelFortschritt(i_cAnzahlSchritte, iSchuelerAnzahl, iUeberAllesSchritt, iAktuellerSchritt, 'Klasse: ' + sKlasse + ' Schüler: ' + sName + ' eingelesen', hstEinlesen);
          end;
        end else
        begin
          GeneriereDoppelFortschritt(i_cAnzahlSchritte, 1, iUeberAllesSchritt, iAktuellerSchritt, 'Klasse: ' + sKlasse + ' übersprungen', hstEinlesen);
        end;
      end else
      begin
        GeneriereDoppelFortschritt(i_cAnzahlSchritte, 1, iUeberAllesSchritt, iAktuellerSchritt, 'Unbekannte Klasse übersprungen', hstEinlesen);
      end;
    end;
    // Zu entfernen Einträge wieder entfernen.
    ILSchuelerIDs.Clear;
    ILLehrerIDs.Clear;
    SLLehrerNachnamen.Clear;
    SLKursNamen.Clear;
    SLSchuelerNamen.Clear;
    SLSchuelerVornamen.Clear;
    SLSchuelerNachnamen.Clear;

    // Gib alle IDs die nun obsolet sind
    GeneriereDoppelFortschritt(i_cAnzahlSchritte, 1, iUeberAllesSchritt, iAktuellerSchritt, 'Überprüfe Datenbank', hstAufraeumen);
    GibObsoleteIDs(ILPersonenIDs, true);
    if ILPersonenIDs.Count = 0 then
      GeneriereDoppelFortschritt(i_cAnzahlSchritte, 1, iUeberAllesSchritt, iAktuellerSchritt, 'Löschen abgeschlossen', hstAufraeumen);
    for i := 0 to ILPersonenIDs.Count - 1 do
    begin
      if iGibAnzahlAusgeliehenZuPID(ILPersonenIDs[i]) = 0 then
      begin
        // Benutzer hat keine Bücher ausgeliehen und ist obsolet -> kann
        //  gelöscht werden, aber zuerst die Kurszuweisungen
        ExecSQL('DELETE FROM Kurszuweisungen WHERE PersonenID = ' + IntToStr(ILPersonenIDs[i]));
        ExecSQL('DELETE FROM Personen WHERE PersonenID = ' + IntToStr(ILPersonenIDs[i]));
      end;
      GeneriereDoppelFortschritt(i_cAnzahlSchritte, ILPersonenIDs.Count, iUeberAllesSchritt, iAktuellerSchritt, 'Lösche Personen', hstAufraeumen);
    end;

    Commit;
    oWorkbook.Close(False, emptyParam, emptyParam, cLCID);
    oExcel.Quit;
  finally
    oExcel.Free;

    ILLehrerIDs.Free;
    ILSchuelerIDs.Free;
    ILPersonenIDs.Free;
    ILKursIDs.Free;
    ILExemplarIDs.Free;

    SLKursNamen.Free;
    SLLehrerNachnamen.Free;
    SLSchuelerNamen.Free;
    SLSchuelerNachnamen.Free;
    SLSchuelerVornamen.Free;
  end;
end;
Ich weiß, es gibt einige Stellen die man mit Parametern machen sollte, aber darum wollte ich mich eh erst in der nächsten Woche kümmern.

MfG
Fabian

p80286 9. Mär 2010 10:34

Re: Schnellste Insert Möglichkeit für eine DB?
 
Hallo xzise,

zunächst einmal, diese Auftrennung in Nachname und Vorname, und die nachfolgende Kombination zumindestens bei den Schülern erscheint mir doch sehr obskur. Oder habe ich die Funktion als Index übersehen?

wenn ich Deine Sourcen auf die SQL-Relevanz verkürze bleibt nur noch das übrig:
Code:

    // Alle Kurse und Kurszuweisungen löschen, die nicht Hauptkurse sind
    EntferneZuSQL('Kurse', 'Hauptkurs <> 0');
   
    EntferneZuSQL('Kurszuweisungen', 'KursID IN (SELECT KursID FROM Kurse WHERE Hauptkurs <> 0)');
   
    // Und dann die Schüler auf obsolet setzen
    ExecSQL('UPDATE Personen SET Obsolet = -1 WHERE HauptKursID != 0');
   

    BeginTransaction;
Zunächst steht da ziemlich verloren ein einsames BeginTransaction, nur noch gefolgt von Datenmanipulationen aber ohne irgendeinen Datenbankbezug (was hab ich da übersehen?).

Und was macht EntferneZuSql ? Wenn ich das richtig verstanden habe, wird jedes mal auf der Datenbank eine wílde Datensammlung erzeugt, die dann wieder bereinigt wird? (Hauptkurs oder nicht)
Dieser "Datenmissbrauch" ist die Grundlage von Chaos-Programmen. Wenn man das Geschlecht einer Person bestimmen/dokumentieren will, dann braucht's ein Feld Geschlecht und keine Umwege über Vorname, Schuhgröße, Haarlänge und was für kreative Ideen da noch herum schwirren. (Übrigens, das der Titel bei Lehrer die ersten fünf Stellen des Namens belegt ist auch so eine Krücke die Fehler geradezu provoziert)

Da sollte das Konzept, das dahinter steht einmal überdacht werden.

Wenn es Dir darum geht, Dein Programm zu beschleunigen, dann solltest Du von diesem
Code:
 GeneriereDoppelFortschritt(i_cAnzahlSchritte...
Abstand nehmen, denn das ist ein echter Zeitfresser.

Zitat:

Aber die Frage die sich mir stellt, ist halt ob ich zwei Queries parallel laufen haben kann.
Das ginge, aber was soll es bringen? Die query die als erste startet, hat den Datenbestand mehr oder weniger exclusiv im Zugriff (kommt auf die dahinter liegende "Sperrungsphilosophie" an) die zweite muß dementsprechend warten. Wenn Du Zeit sparen willst, solltest Du Dir dein Programm einmal sehr kritisch anschauen, und vor allem die Frage stellen wofür das, was da gemacht wird, eigentlich gut ist.

gruß
K-H

xZise 9. Mär 2010 10:56

Re: Schnellste Insert Möglichkeit für eine DB?
 
Moin,
ich weiß, es ist nicht gerade ideal gelöscht, aber wir bekommen halt eine Liste mit Namen von Schülern. Das heißt wir können nicht (was wesentlich besser ist) testen, ob eine PersonenID noch existiert, sondern stattdessen uns darauf verlassen, dass es keine zwei Personen mit den gleichen Vornamen und Nachnamen parallel gibt.

Und ich verstehe deine „SQL-Relevanz“ nicht. Das alles vor den BeginTransaction bereitet die Datenbank vor. Es ist halt nicht eben nur eine einfache Personenliste, sondern wir speichern zusätzlich auch die Kurse/Klassen der einzelnen Schüler. Dazu gibt es die Tabelle Kurse und Kurszuweisungen. Der erste Befehl, löscht nun alle Kurse, die ein Hauptkurs sind während der zweite Befehl dann alle Zuweisungen löschen soll. Das heißt er löscht die Information, welche Schüler in den Kursen waren, die gelöscht wurden. Okay ich glaube das muss andersherum ausgeführt werden.
Der dritte Befehl, setzt dann präventiv alle Schüler erst mal auf überflüssig (der Hauptkurs ist eben nicht 0, das sind die Lehrer) also Obsolet ist nicht 0.

So und dann kommen wir in den interessanten Bereich:
Nun gehen wir jede Klasse der Exceltabelle durch. Oben rechts steht dann immer "Herr/Frau ...", nagut das es immer 5 sind, ist nicht direkt gegeben, das schaue ich mir mal an, wie man das anders macht (wohl eher dann mit Pos etc.).

Also ermittelt er erstmal den Lehrer/die Lehrerin, wenn sie nicht existiert, MUSS sie erstellt werden, weil daraufhin dann wieder ein neuer Kurs angelegt wird und dieser MUSS umbedingt eine Valide LehrerID haben!

Dann geht er jeden Schüler dieses Kurses durch und liest den Namen ein und prüft, ob er bereits existiert. Wenn er nicht existiert (bzw. der Vorname und Nachname), dann ruft er iFügeSchülerHinzu auf, welche einen Schüler hinzufügt. Alternativ setzt er den Schüler auf nicht überflüssig (Obsolet = 0). Zusätzlich setzt er dann auch die neue HauptkursID.

Okay ich habe mich zu lange nicht damit beschäftigt, weshalb da nicht nur zwei SQL Statements vorkommen:
Um eine Person hinzufügen (das ist der Inhalt von iFuegeSchuelerHinzu):
SQL-Code:
INSERT INTO Personen(Name,Vorname,HauptKursID,Obsolet) VALUES ("AName", "AVorname" , 0, 0)
So und für jede Person gilt das (das ist der Inhalt von WeiseHauptKursIDZuPIDZu, welche von iFuegeSchuelerHinzu aufgerufen wird!):
SQL-Code:
DELETE FROM Kurszuweisungen WHERE PersonenID = ASchuelerID AND KursID = AKursID
UPDATE Personen SET HauptKursID = AKursID WHERE PersonenID = APersonenID
INSERT INTO Kurszuweisungen (PersonenID, KursID) VALUES (ASchuelerID, AKursID)
Okay, das DELETE Statement ist überflüssig, weil wir zu Anfang da ja aufgeräumt haben.
Und Alle Werte mit A.... sind Variablen und beim hinzufügen der Person, bekomme ich die SchülerID zurückgegeben.

Und ganz zum Schluss, lösche ich dann alle Schüler, die obsolet markiert wurden.

Sofern das nicht weiter zu optimieren ist, lasse ich dennoch das GeneriereDoppelFortschritt( drin, damit der Anwender eine Rückmeldung bekommt.

MfG
Fabian

Sharky 9. Mär 2010 12:07

Re: Schnellste Insert Möglichkeit für eine DB?
 
Hai ihr,

hat das mti der "Schülerliste" noch etwas mit dem Ursprungsthema zu tun?

p80286 9. Mär 2010 13:46

Re: Schnellste Insert Möglichkeit für eine DB?
 
@Sharky
Ich denke jetzt wieder

@xZise
jetzt hast Du die Chance über die Parameter Geschwindigkeit zu machen z.b. so:
Delphi-Quellcode:
  q.sqltext:='INSERT INTO Personen(Name,Vorname,HauptKursID,Obsolet) VALUES (:AName, :AVorname , 0, 0);
  for i:=0 to liste.count-1 do begin
    q.parambyname('Aname').asstring:=liste[i].Name;
    q.parambyname('Avorname').asstring:=liste[i].Vorname;
    q.sqlexec;
  end;
So sollte es im Prinzip ablaufen. Der Einfacheit halber ist bei mir Liste keine Stringliste, aber ich denke das Prinzip ist klar.

SQL-Code:
DELETE FROM Kurszuweisungen WHERE PersonenID = ASchuelerID AND KursID = AKursID
UPDATE Personen SET HauptKursID = AKursID WHERE PersonenID = APersonenID
INSERT INTO Kurszuweisungen (PersonenID, KursID) VALUES (ASchuelerID, AKursID)
auch hier solltest Du (wenn möglich!) erst alle DELETE-Anweisungen, dann die UPDATEs und dann die INSERTs ausführen lassen.
Natürlich unter Ausnutzung der Parameter.
was die Transaktion angeht, würde ich jede for i:=.Schleife in eine Transaktion packen, aber das ist eine reine Bauchempfehlung.

Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:38 Uhr.
Seite 5 von 5   « Erste     345   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz