Einzelnen Beitrag anzeigen

Benutzerbild von xZise
xZise

Registriert seit: 3. Mär 2006
Ort: Waldbronn
4.303 Beiträge
 
Delphi 2009 Professional
 
#44

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

  Alt 8. Mär 2010, 16:58
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
Fabian
Eigentlich hat MS Windows ab Vista den Hang zur Selbstzerstörung abgewöhnt – mkinzler
  Mit Zitat antworten Zitat