Zoiets hadden wij ook.
En slecht datamodel, ach, als er na 3 jaar weer eens functionaliteit wordt toegevoegd (zoals een tijd terug, emailadres toevoegen bij een relatiebestand), dan vind ik dat wel meevallen. In ons geval was het iig geen onderdeel van de originele applicatie.
Hoe dan ook.
Wij maken al onze tabellen met een unit die we TableManager hebben genoemd.
Op het moment dat je die aanmaakt, controleerd die allemaal zaken, en op het moment dat je een tabel opent, kijkt hij of deze al bestaat. Zo niet, simpel, aanmaken.
Daaruit volgt dat in die Tablemanager alle tabeldefinities staan. Hier kun je dus een tellertje bijzetten hoeveel kolommen er zijn.
Uit TTable.FieldDefs kun je het aantal velden halen, verschilt dat met het tellertje dat je hebt, dan heb je dus te maken met een oude tabel.
Oplossing:
code:
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
| CopyFile(huidigeMap + bestandsNaam, backupMap + bestandsNaam);
OudTable := TTable.Create(nil);
OudTable.DatabaseName := backupMap;
OudTable.TableName := bestandsNaam;
OudTable.TableType := ttDbase;
OudTable.Active := true;
OudTable.First;
// Ik weet niet hoe het daar gaat, maar bij ons is dit de normale manier van
// het aanmaken van een tabel:
NieuwTable := TableManager.GiveTable(welke_wil_je_hebben);
NieuwTable.Active := true;
while not OudTable.Eof do
begin
NieuwTable.Append;
voor i = 0 tot aan totaal aantal velden in NieuwTable do
begin
try
NieuwTable[NieuwTable.IndexDefs.NameOf(i)] :=
OudTable[NieuwTable.IndexDefs.NameOf(i)]; // OID... Iig de naam opzoeken
except
// Exception komt voor bij nietbestaande velden in OudTable;
end;
end;
NieuwTable.Post;
OudTable.Next;
end; |
Eventueel nog wat checks als de nieuwe velden required zijn, maar (nu dus) leeg, dan kun je een default waarde invullen.
Is misschien een vrij ranzige methonde, je kunt de try..except eruitwerken door iedere keer te controleren in de IndexDefs of de veldnaam bestaat en zo, maar zo updaten ze bij ons dus iedere nieuwe versie die een klant krijgt (onderhoudscontract) alle ondertussen 130 tabellen. Wij doen het dus neit on the fly, maar in een apart programma, bij een nieuwe release.
Wat je eventueel nog kunt doen om vooral bij grote tabellen (en dat is al vanaf 3k records DUIDELIJK merkbaar als je redelijk wat indexen hebt) de snelheid omhoog te jagen, is bij het aanroepen / maken van de nieuwe tabellen de indexen nog niet toe te voegen, maar deze naderhand toe te voegen. Dat brengt wel een grotere overhead mee, want nu moet de update-procedure wel ALLE indexen van alle tabellen kennen, wat dan ook de reden is dat we dat bij ons niet doen.
Ik heb zo de code niet bij de hand (zit thuis atm) dus ik kan wat vergeten zijn / verkeerd hebben, maar zoals hierboven is wel het algemene idee
Aan het alter table statment heeft nog nooit iemand hier (bij ons) gedacht... Komt omdat wij alles met TTable doen ipv met TQuery.
Hoe dan ook, zo kun je het beste uit 2 werelden combineren, want dan kun je met TTable.FieldDefs de veldnamen opzoeken, kijken welke je mist, en die dan met het SQL-statement toevoegen. Dan ben je ook van die try..except af, want eigenlijk is dit geen fout-afhandeling