Trick 75: Index ändern on-the-fly
Bestimmte Einträge im laufenden Betrieb ändern
Aufgabe: Schnell mal eben für eine Anzahl von Sätzen einen bestimmten
Registereintrag ändern.
Warum das?
Wer kennt es nicht: Man macht an den Indexparametern eine ganz kleine
Änderung, aber a99 ist zu dumm, dann schnell mal eben die nicht mehr
korrekten Schlüssel automatisch rauszusuchen und -zuwerfen und die
nunmehr korrekten einzusortieren.
Warum das so ist? Nun, a99 kriegt einfach gar nicht mit, daß man was
geändert hat - es prüft nicht ständig, ob die Datei noch so ist wie
vorher - und falls nicht, dann genau das Richtige zu tun. Das wäre
leider zuviel verlangt, man muß also selber dran denken, daß man den
Index dann erneuert.
Ha! Index erneuern, das ist bei Kleinbanken kein Problem, aber bei
sehr großen braucht's massig Zeit und ist im Netz auch nur dann
möglich, wenn gerade keiner an der Datenbank arbeitet, und das kann
schon ein arges Ärgernis sein; in einem 24/7-Betrieb geht das gar
nicht!
Aber FLEX birgt das Potential für einen pfiffigen Trick, und der geht so:
Zuerst die Ergebnismenge aller Sätze bilden, bei denen die
Änderung sich auswirken würde.
Dann einen FLEX schreiben, der
a) aus einem Satz den nicht mehr gültigen Schlüssel bildet und
diesen löscht (mit ixdel ...)
b) aus demselben Satz den nunmehr gültigen Schlüssel bildet und
diesen einfügt (mit ixadd ...)
Es folgt das Kochrezept, an das man sich in jedem Fall halten kann.
(Doku zu den zwei Befehlen: h xixadd. Darin auch Hinweis auf einen
aufwendigeren FLEX umindex.flx, der sich empfiehlt, wenn besonders
viele Schlüssel zu ändern sind; darauf wurde auch in der Vb.202
schon kurz aufmerksam gemacht. Er löscht zunächst *alle* Schlüssel
eines Satzes nach Maßgabe der alten Parameter und speist dann alle
nach Vorschrift der neuen neu ein. Je nach Menge dauert das viel
länger. umindex.flx ist im Gesamtpaket mit drin.)
// Ergebnismenge der relevanten Sätze vorher bilden
first
:loop
// den alten, nicht mehr korrekten Schl. bilden
// und zwar mit Index-Präfix, z.B |7, ohne Spatium dahinter
var "|..." ...
ins #uzA
var i " " #uzA
ixdel
// den neuen, jetzt korrekten Schl. bilden
var "|..." ...
ins #uzN
var i " " #uzN
ixadd
:nxt
next
if yes jump loop
mes ERLEDIGT!
Statt var "..." ... ist natürlich jeweils ein geeigneter Algorithmus
für den betr. Schlüssel einzusetzen. Dazu sind evtl. mehrere Befehle
nötig. Insbes. kann man mit xcode ip oder xcode iq die Umcodierung
der Indexparameter mit heranziehen.
Auch umgekehrt, zuerst neu dann alt, ist es möglich. Oder wahlweise nur
den alten, nicht mehr benötigten Schlüssel löschen oder nur den neuen,
den es bisher noch nicht gab, erzeugen.
Ferner ist es natürlich auch möglich, statt nur eines Schlüssels gleich
mehrere zu löschen und/oder neu einzuspeisen; dann erweitert man eben
die Sache um entsprechende Abschnitte. Ratsam ist natürlich immer, es
erst mit einer kleinen Erg.Menge zu testen...
Aber was, wenn man auf keine Weise die Ergebnismenge aller betroffenen
Sätze bilden kann? Dann erweitert man die Schleife mit first # und
next # eben auf die Gesamtbank und startet es vor der Mittagspause.
Aber Achtung: Statt einfach nur next # muß es dann so lauten:
:nxt
next #
if deleted jump nxt
if not cancel jump loop
denn es könnte sich bei dem mit next # geladen Satz um einen
gelöschten handeln ("deleted"), so einer ist zu überspringen.