De meeste – zo niet alle - programmeurs weten, dat elke tabel een sleutelveld zou moeten hebben, voornamelijk om relaties met andere tabellen tot stand te brengen. Het kan zijn, dat je betekenisloze of betekenisvolle sleutels gebruikt. Betekenisloos wil zeggen dat er geen enkele informatie in de sleutel zit, meestal een opeenvolgend nummer. Betekenisvol wil zeggen dat in het sleutelveld informatie is verwerkt, bijvoorbeeld een deel van een naam of een afkorting. Het gebruik van betekenisvolle sleutels is, wat mij betreft, sterk af te raden, voornamelijk omdat de kans dat aanwezig is, dat betekenisvolle informatie ooit wijzigt. In dat geval moet je in alle gerelateerde tabellen de (verwijzende) sleutels wijzigen.
Tot en met versie 7 van FoxPro was het nodig om de vulling van een sleutelveld zelf te regelen. Daarvoor zijn verschillende varianten denkbaar. Een belangrijk punt van aandacht is het geval van een multi-user omgeving in combinatie met gebufferde data. Een sleutelwaarde mag tenslotte maar 1 keer uitgegeven worden.
Een veel gebruikte strategie is een aparte sleutelwaarden-tabel waarin van alle tabellen de laatst uitgegeven sleutel staat. Door het gebruik van bijvoorbeeld een stored procedure kun je het sleutelveld vullen.
Foxpro 8
FoxPro 8 biedt ons de mogelijkheid om een autoincrement veld toe te voegen aan de tabel, zodat e.e.a. automatisch voor je geregeld wordt. Bij het aanmaken van dit veld kun je aangeven wat de volgende sleutel moet zijn en wat de stapgrootte is voor het uitgeven van nieuwe sleutels. Het autoincrement veld kun je zowel in de Table Designer als via het ALTER TABLE commando aan de tabel toevoegen. In een tabel kun je meerdere autoincrement velden gebruiken, maar of dat een nuttige toepassing heeft, weet ik niet.
Het veld dat je als een autoincrement veld gebruikt, is read only en kan dan ook niet geupdate worden. Dat kan makkelijk leiden tot foutsituaties. Stel, je wilt een record kopiëren en je zou daarvoor het GATHER/SCATTER commando willen gebruiken:
|
SELECT (tabel) GO TOP && stel je wilt het bovenste record kopiëren SCATTER MEMVAR MEMO APPEND BLANK GATHER MEMVAR MEMO |
Dan geeft dit de foutmelding “FIELD cid IS READONLY”
Natuurlijk kun je dit afvangen door een ..EXCEPT.. op te geven bij de SCATTER, maar dan moet je wel expliciet invullen (of uitvragen) wat de autoincrement velden zijn.
Gelukkig is er ook een andere oplossing: na het uitvoeren van het commando “SET AUTOINCERROR OFF” wordt de fout genegeerd. De scope van dit commando is helaas wel gelimiteerd tot de huidige datasessie, dus als je private datasessies gebruikt, is het niet afdoende om in de initialisatie van je applicatie dit commando te geven.
Een andere mogelijkheid is het zetten van de property “AutoIncError” d.m.v. het CURSORSETPROP statement; in dat geval geldt het commando alleen voor de tabel waarvoor de property gezet is.
Afields
Voor de autoincrement functie is de AFIELDS functie uitgebreid. Het array dat wordt geretourneerd, bevat nu twee kolommen meer, namelijk positie 17: “NextValue for autoincrementing” en 18: “Step for autoincrementing”. M.a.w. als je wilt weten wat de volgende waarde is die uitgegeven gaat worden (of welke als laatste uitgegeven is), dan is dit de functie die je daarvoor kan gebruiken.
Buffering en views
Als je buffering gebruikt op een tabel werkt de autoincrement functie prima: het autoincrement veld wordt netjes opgehoogd. Bij het gebruik van een local view heb je wel een probleem, want helaas werkt daar de autoincrement functie niet eerder dan dat je een TABELUPDATE() doet. Dat kan best lastig zijn als je parent/child tabellen hebt, waarbij je het sleutelveld van de parent tabel weg wil schrijven in het foreign key veld van de childtabel.
Nadelen aan het gebruik van de autoincrement velden
Er zitten ook nadelen aan het gebruik van autoincrement velden. Één daarvan is het verlies aan performance bij het gebruik van dit veld in combinatie met buffering, maar je moet niet vergeten dat je eigen procedure die de primary key regelt, ook performance kost.
En als je de tabel in een eerdere versie van FoxPro opent, zegt-ie “not a table”, maar ja wie wil er nog terug naar eerdere versies …