Einzelnen Beitrag anzeigen

manfred_h

Registriert seit: 4. Nov 2005
Ort: Basel
442 Beiträge
 
Delphi XE2 Enterprise
 
#1

Datenbank ( Tabellen ) Aktualisierung

  Alt 12. Aug 2010, 18:13
Datenbank: Firebird • Version: 2.1 • Zugriff über: Fibplus
Hallo zusammen

vor längerer Zeit habe ich hier im Forum Bsp. gefunden um eine DB zu aktualisieren. ( Leider weiss ich nicht mehr von wem / Hatte es im alten Forum in den "gespeicherten Themen" die sind nun aber leider weg.. )

Folgendes ist der Fall:
Tabelle in der DB:
Code:
SELECT
    ID,
    DB_DATE,
    MAJOR,
    MINOR,
    REL,
    BUILD,
    SCRIPT,
    RUNNED,
CAST(CAST(MAJOR AS BIGINT)*1000000000+MINOR*1000000+REL*1000+BUILD AS BIGINT) AS VERSION
FROM
    G_DB_VERSION
WHERE MAJOR < :MAJOR1 OR (MAJOR = :MAJOR2 AND (MINOR < :MINOR1 OR (MINOR = :MINOR2 AND (REL < :RELEASE1 OR (REL = :RELEASE2 AND (BUILD <= :BUILD))))))
ORDER BY RUNNED DESC, MAJOR, MINOR, REL, BUILD
Überprüfung der Version:
Delphi-Quellcode:
procedure TDM_update.CheckDBVersion;
var
 AskFirst : boolean ;
 LastRunned, v, NV : int64 ;
 NeedRestart, BackupOK : boolean ;
begin
  dm.DB_Gideons.Connected:= true;
  FI.Filename := application.exename ;
  v := FI.Version.Major*1000000000 + FI.Version.Minor*1000000 +
       FI.Version.Release*1000 + FI.Version.Build ;
   //showmessage (inttostr(v)) ;
  AskFirst := true ;
// AskFirst := false ;
  SkriptError := false ;
  NeedRestart := false ;

  UpdateVersionTableRecords ;

  with sqlVersion do
  begin
    close ;
    parambyname ('Major1').AsInteger := FI.Version.Major ;
    parambyname ('Minor1').AsInteger := FI.Version.Minor ;
    parambyname ('Release1').AsInteger := FI.Version.Release ;
    parambyname ('Major2').AsInteger := FI.Version.Major ;
    parambyname ('Minor2').AsInteger := FI.Version.Minor ;
    parambyname ('Release2').AsInteger := FI.Version.Release ;
    parambyname ('Build').AsInteger := FI.Version.Build ;
    open ;

    if Locate ('RUNNED',1,[]) then
    begin
// if Locate ('RUNNED',1,[]) then begin
     { Blättern bis letzen Runned=true gefunden. Dann weiter bis Runned=false }
     { jedoch Version > LastRunned }
      ID := -1 ;
      LastRunned := 0 ;
      repeat
        if FieldByName ('Runned').AsBoolean
        then LastRunned := FieldByName ('Version').asInteger ;
        if not FieldByName ('Runned').AsBoolean
        then ID := FieldByName ('ID').AsInteger ;
        if not EOF then next ;
      until EOF or (ID <> -1) ;
      if ID <> -1 then begin
        Locate ('ID',ID,[]) ;
        ID := FieldByName ('ID').AsInteger ;
        NV := FieldByName('Version').AsInteger ;
        while (not EOF) and (NV < LastRunned) do begin
           ID := -1 ;
           next ;
           if not eof then begin
              NV := FieldByName('Version').AsInteger ;
              ID := FieldByName ('ID').AsInteger ;
           end ;
        end ;
        Locate ('ID',ID,[]) ;
      end ;
    end else
    begin
      { Einfacher Fall: Alle Skripte ausführen }
      First ;
      ID := FieldByName ('ID').AsInteger ;
    end ;

      //showmessage ('Entgültige ID: ' + inttostr(ID)) ;

    while (not EOF) and (not SkriptError) and (not FieldByName('Runned').AsBoolean) and (ID <> -1) do begin
    if AskFirst
      then if MessageDlg('Datenbankskripte ausführen ?', mtConfirmation, [mbYes, mbNo], 0) = mrYes
        then
        begin
          case MessageDlg('Soll vor der Ausführung der Skripte ein Datenbank Backup erfolgen?', mtConfirmation, [mbYes, mbNo, mbAbort], 0) of
            mrYes : if not (MakeBackup) then
              begin
                close ;
                exit ;
              end ;
            mrAbort :
               begin
                 close ;
                 exit ;
               end ;
          end ;
        NeedRestart := true ;
        DM.DB_Gideons.Close;
        DM.DB_Gideons.Open ;
        Open ;
        Locate ('ID',ID,[]) ;
        AskFirst := false ;
        end
        else begin
                close ;
                exit ;
             end ;
      // Backup wird in jedem Fall durchgeführt
      MakeBackup;
      //
// MessageDlg(sqlVersion.SelectSQL.Text, mtInformation, [mbOK], 0);
// hier tritt der Fehler auf:
      RunDBScript (FieldByName('Major').AsInteger,
                  FieldByName('Minor').AsInteger,
                  FieldByName('Rel').AsInteger,
                  FieldByName('Build').AsInteger) ;
      next ;
    end ;
      close ;
   end ;

   if NeedRestart then begin
      MessageDlg('Die Anwendung muss nun neu gestartet werden.', mtInformation, [mbOK], 0);
// shellexecute (frm_main.handle,'open',PChar(application.exename),'',PChar(ExtractFilePath(application.exename)),SW_SHOWNORMAL) ;
      application.terminate ;
   end ;
end;
Ausführen des Updates aus einer sql Datei:
Delphi-Quellcode:
procedure TDM_update.RunDBScript (Major,Minor,Release,Build : integer) ;
var
 V, Filename : string ;
begin
  V := format('v.%d.%d.%d.%d',[Major,Minor,Release,Build]) ;
  frm_ScriptProgress := Tfrm_ScriptProgress.create (Self) ;
  with frm_ScriptProgress do
  begin
    lblVersion.caption := V ;
    PB.Position := 0 ;
    Filename := ScriptsDir + V + '.txt' ;
    show ;
    if FileExists (Filename) then
    begin
      DM.pFIBScript.Script.LoadFromFile (Filename) ;
      DM.pFIBScript.ExecuteScript;
      if not (SkriptError) then
      begin
        SetScriptRunStatus (sqlVersion.FieldByName('Major').AsInteger,
                            sqlVersion.FieldByName('Minor').AsInteger,
                            sqlVersion.FieldByName('Rel').AsInteger,
                            sqlVersion.FieldByName('Build').AsInteger,
        // true,script.script.text) ;
                            true,DM.pFIBScript.script.text) ;
      end ;
      Refresh ;
      sleep (800) ;
    end else
    begin
      MessageDlg(format('Skriptdatei %s nicht gefunden.'+#13+#10+''+#13+#10+
                       'Update konnte nicht überspielt werden. Programm wird beendet.',[extractFilename(Filename)]), mtError, [mbOK], 0);
      application.Terminate ;
    end ;
  end ;
  frm_ScriptProgress.free ;
end ;
Das Problem ist dass eine Fehlermeldung erscheint:
Zitat:
Exception class EDatabaseError with message 'sqlVersion: Field 'Rel' not found'.
Sobald dieser Code aufgerufen wird:
RunDBScript (FieldByName('Major').AsInteger,
FieldByName('Minor').AsInteger,
FieldByName('Rel').AsInteger,
FieldByName('Build').AsInteger) ;


Was ich nicht verstehe ist dass sqlVersion das Feld Rel in der DB nicht findet, dieses ist aber vorhanden...
Auszug aus der DB
Code:
CREATE TABLE G_DB_VERSION (
    ID      D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    DB_DATE D_DATE NOT NULL /* D_DATE = DATE */,
    MAJOR   D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    MINOR   D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    REL     D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    BUILD   D_INTEGER NOT NULL /* D_INTEGER = INTEGER */,
    SCRIPT  VARCHAR(32762) CHARACTER SET ASCII,
    RUNNED  D_SMALLINT /* D_SMALLINT = SMALLINT */
);
Bin dankbar für jeden Tipp.
Manfred
  Mit Zitat antworten Zitat