Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   DBF Spaltennamen ändern (https://www.delphipraxis.net/201614-dbf-spaltennamen-aendern.html)

Kondzie 7. Aug 2019 14:41

Datenbank: DBF • Version: 3 • Zugriff über: UniDac

DBF Spaltennamen ändern
 
Hallo liebe Community!

Ich versuche gerade kopfzerbrechend einen Fehler bei mir zu finden und komme einfach nicht weiter...

Grundgedanke:
Ich möchte/muss einige Spaltennamen in DBASE III umbenennen. Da der ODBC-Treiber "dumm" ist, klappt ja kein "ALTER TABLE".
Deswegen speichere ich mir meine DBF-File in eine DBTable und führe dann mit einem Query ein "DROP", sowie ein "CREATE TABLE" mit den veränderten Spaltennamen aus.
Danach lade ich mir über den Query alle Daten aus meiner DBTabelle in die neu erstellte DBF-Tabelle.
Das möchte ich natürlich für mehrere Tabellen machen und führe deswegen ein Loop durch meinen "Datenbank-Ordner".
Diese Prozedure funktioniert einmnal und beim Laden der nächsten Tabelle in die DBTabelle tritt ein Fehler auf... ziemlich unlogischer, nebenbei bemerkt... :
"Es ist eine Exception der Klasse ESQLiteError mit der Meldung 'database table is locked' aufgetreten".

Ich verstehe weder, warum eine SQLite-Exception auftritt, noch warum die Tabelle locked ist, da ich sie ja noch nicht mal verwendet habe..

Hier meine Prozedur/Funktion:
Code:
function Tfrm_Main.Alter_DBF_Tables: Boolean;
const
  aTables:Array [0..6] of String = ('ALARM','CODBU','BACOFFST','HCLESE','HCRCAGRP','PERSCOD','SYSPARA');
var
  I,itablecnt,ibookingcnt: Integer;
  stable:string;
begin
  UniTableSource.active:=false;
  UniTableSource.Connection:=UniConDBF;
  UniQuery.Active:=false;
  UniQuery.Connection:=UniConDBF;
  ibookingcnt:=1;
  itablecnt:=0;

  while itablecnt< length(aTables) do
    begin

      stable:= aTables[itablecnt];

      if Check_BookingTable(sTable.ToUpper) then
        begin
          stable:= Format(stable+'%.*d',[2,ibookingcnt]);
          Inc(ibookingcnt);
        end;

      if not fileexists(UniConDBF.Database+sTable+'.dbf') then
        begin
          if not Check_BookingTable(sTable.ToUpper) then
              Inc(itablecnt)
          else if ibookingcnt>12 then
            Inc(itablecnt);

          continue;
        end;


      UniTableSource.active:=false;
      UniTableSource.TableName:=stable;
      UniTableSource.active:=true;

      UniQuery.SQL.Text:='DROP TABLE '+stable;
      UniQuery.ExecSQL;

      UniQuery.SQL.Clear;
      UniQuery.SQL.Add('CREATE TABLE '+stable+'(');
      for I := 0 to UniTableSource.Fieldcount-1 do
        begin
          if Check_Column(UniTableSource.Fields[i].FieldName.ToUpper) then
            UniQuery.SQL.Add('A'+UniTableSource.Fields[i].FieldName.ToUpper+' ')
          else
            UniQuery.SQL.Add(UniTableSource.Fields[i].FieldName.ToUpper+' ');

          UniQuery.SQL.Add(Lib.DataTypetoStrDBF(UniTableSource.Fields[i].DataType).ToUpper);
          if Lib.DataTypetoStrDBF(UniTableSource.Fields[i].DataType).ToUpper='CHAR' then
            if UniTableSource.Fields[i].DataSize>254 then
              UniQuery.SQL.Add(' (254)')
            else
              UniQuery.SQL.Add(' ('+UniTableSource.Fields[i].DataSize.ToString+')');
          if i<UniTableSource.Fieldcount-1 then
            UniQuery.SQL.Add(',')
          else
            UniQuery.SQL.Add(')');
        end;
      UniQuery.ExecSQL;

      UniQuery.SQL.Clear;

      while not UniTableSource.EOF do
        begin
          UniQuery.SQL.Clear;
          UniQuery.SQL.Add('INSERT INTO '+stable+' VALUES(');
          for I := 0 to UniTableSource.Fieldcount-1 do
            begin
              if Lib.DataTypetoStrDBF(UniTableSource.Fields[i].DataType).ToUpper='CHAR' then
                UniQuery.SQL.Add(QuotedStr(UniTableSource.Fields[i].AsString))
              else
                UniQuery.SQL.Add(UniTableSource.Fields[i].AsString);

              if i<UniTableSource.Fieldcount-1 then
                UniQuery.SQL.Add(',')
              else
                UniQuery.SQL.Add(');');
            end;
          UniQuery.ExecSQL;
          UniTableSource.Next;
        end;


      if not (Check_BookingTable(sTable.ToUpper)) then
        begin
          Inc(itablecnt);
          ibookingcnt:=1;
        end;

    end;

end;
Ich hoffe Ihr könnt mir irgendwie weiter helfen .. ich steh auf dem Schlauch:cry:

Grüße Kondzie!

hoika 7. Aug 2019 20:55

AW: DBF Spaltennamen ändern
 
Hallo,
viel zu wenig Infos.

Welchen Datentyp haben deine verwendeten DB-Komponenten (UniXXX).
In welcher Zeile konkret kommt der Fehler bei der zweiten Tabelle.

Und es geht wirklich um DBase3 ???

PS:
Der "normale" weg wäre ja das Anlegen der neuen Spalte,
ein Rüberkopieren der Werte (Update) und löschen der alten Spalte.
Warum das Drop Table?

hoika 7. Aug 2019 21:41

AW: DBF Spaltennamen ändern
 
Hallo,
kurz gestöbert

Es gibt ja TDbf

https://sourceforge.net/projects/tdbf/

und dort

procedure RestructureTable(DbfFieldDefs: TDbfFieldDefs; Pack: Boolean);

Ich würde das mal damit probieren.

Kondzie 8. Aug 2019 06:54

AW: DBF Spaltennamen ändern
 
Vielen Dank für deine bisherigen mühen Heiko!

Zitat:

Welchen Datentyp haben deine verwendeten DB-Komponenten (UniXXX).
Ich weiß nicht, was du in Klammern mit dem UniXXX meinst, aber eigentlich werden nur Numeric,Char und Date verwendet.

Zitat:

In welcher Zeile konkret kommt der Fehler bei der zweiten Tabelle.
Der Fehler tritt auf, wenn ich die nächste DBF-Tabelle in die DB-Tabelle lade.
Also hier:
Code:
UniTableSource.active:=false;
UniTableSource.TableName:=stable;
UniTableSource.active:=true;
Zitat:

Und es geht wirklich um DBase3 ???
Tatsächlich dachte ich das. Jetzt bin ich selber verwirrt. Also Die DBF-Dateien sind DBASE3, aber in meinem ConnectionString benutze ich das Format DBASE4 .... wenn ich es im ConnectionString umstelle, dann bekomme ich Datentyp-Fehler... aber darum geht es hier ja hoffentlich nicht ?

Zitat:

Der "normale" weg wäre ja das Anlegen der neuen Spalte,
ein Rüberkopieren der Werte (Update) und löschen der alten Spalte.
Warum das Drop Table?
Da ich ja den Tabellennamen beibehalten will, kann ich kein "CREATE" machen, da ja der Name zu diesem Zeitpunkt noch besteht. Deswegen erst "Drop", dann "CREATE".
Oder liege ich da jetzt komplett Falsch?

Zitat:

Es gibt ja TDbf
Ja das könnte ich auch mal ausprobieren. Danke dafür.

BerndS 8. Aug 2019 07:19

AW: DBF Spaltennamen ändern
 
Da sich bei TDBF seit 11/2015 nichts mehr tut, wäre für die neueren Delphi Versionen TVKDBF wahrscheinlich besser geeignet.

Nachtrag: RestructureTable gibt es in leider nicht. Müsste man dann selber umsetzen.

exilant 8. Aug 2019 08:33

AW: DBF Spaltennamen ändern
 
Der Header von DBFs ist trivial. Kannst Du mit jedem Hex-Editor patchen.


DBF Header Structure

Kondzie 8. Aug 2019 08:43

AW: DBF Spaltennamen ändern
 
Zitat:

Der Fehler tritt auf, wenn ich die nächste DBF-Tabelle in die DB-Tabelle lade.
Also hier:
markieren
Code:
UniTableSource.active:=false;
UniTableSource.TableName:=stable;
UniTableSource.active:=true;
Das stimmt nicht! Der Fehler tritt auf, wenn ich Versuche die nächste Tabelle zu löschen, also hier:

Code:
UniQuery.SQL.Text:='DROP TABLE '+stable;
UniQuery.ExecSQL;

Der ganze Sinn hinter der Sache ist ja auch, dass ich von DBASE loskommen möchte. Da es aber in manchen Tabellen unüberlegte Spaltennamen gibt, wie "DATE/TIME/TYPE" etc., fällt das Konvertieren nach z.B. SQL Server schwer. Deswegen muss ich das erstmal ändern.


Anscheinend gebe ich irgendeine Instanz nicht ordentlich wieder frei. Aber dafür fehlen mir die nötigen Kenntnisse über Delphi, da ich ein "Neuling" bin.
Könnt Ihr was in meiner Funktion erkennen, was nicht ordentlich freigegeben ist oder dergleichen?

hoika 8. Aug 2019 09:03

AW: DBF Spaltennamen ändern
 
Hallo,
Zitat:

fällt das Konvertieren nach z.B. SQL Server schwer
Nein, tut es nicht.

Ich hatte mir damals beim Umstieg von Paradox auf Interbase
ein eigenes Copy-Programm geschrieben.
Ich kannte ja die Tabellen mit den "bösen" Feldnamen
und habe die entsprechend berücksichtigt.


Zitat:

Nachtrag: RestructureTable gibt es in leider nicht. Müsste man dann selber umsetzen.
Eben deshalb die alte Version TDbf benutzen.

hoika 8. Aug 2019 09:09

AW: DBF Spaltennamen ändern
 
Hallo,
Zitat:

Anscheinend gebe ich irgendeine Instanz nicht ordentlich wieder frei.
es kann aber auch sein, dass Du das aktuelle Daten-Verzeichnis irgendwie abänderst,
dann findet das Programm die Tabelle wirklich nicht
GetCurrentDir
http://www.delphibasics.co.uk/RTL.as...=GetCurrentDir

Kondzie 8. Aug 2019 09:17

AW: DBF Spaltennamen ändern
 
Zitat:

es kann aber auch sein, dass Du das aktuelle Daten-Verzeichnis irgendwie abänderst,
dann findet das Programm die Tabelle wirklich nicht
Naja ich Lösche und Erstelle neue Tabellen, vielleicht fällt das unter abändern?

Aber ich habe gerade alles versucht um die Instanzen zu schließen. Ich habe jetzt zwischendrin meine Connection gelöscht und neu verbunden, um ganz sicher zu gehen.
Leider funktioniert es auch so nicht.
Ich verstehe einfach nicht, warum die Tabelle, die ich ja noch gar nicht verwendet habe, gesperrt ist.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:46 Uhr.
Seite 1 von 2  1 2      

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