allegro-Fortbildung                                         

   7    Wichtige Dateien
   7.3    Primärschlüssel und automatische Nummernvergabe



Dies ist in erster Linie eine Lektion für Systemverwalter. Sie faßt
Informationen zusammen, die in verschiedene Zusammenhänge gehören und
deshalb im Systemhandbuch getrennt sind, die aber oft zusammen
gebraucht werden. [Den ersten Entwurf zu dieser Lektion lieferte
dankenswerterweise Frau Dr. Koczian, Augsburg]
Als Nur-Anwender können Sie sich heute entspannen, Sie brauchen
diese Dinge nicht zu wissen. Schaden kann's aber nicht.

Ein einfacher und eindeutiger Suchbegriff für jeden Satz einer
Datenbank ist immer nützlich und für bestimmte Arbeiten unentbehrlich.
Das gilt für allegro genauso wie für jedes andere Datenbanksystem.
Einen solchen Suchbegriff nennt man Primärschlüssel.
Diese Lektion will folgende Fragen beantworten:
-- Wozu werden Primärschlüssel speziell in einer allegro-Datenbank
   gebraucht?
-- Was muß bei der Parametrierung geschehen, damit jeder Satz seinen
   Primärschlüssel bekommt?
-- Wie kommt man zu geeigneten Schlüsseln, wenn die Daten nicht
   "von Natur aus" ein passendes Feld enthalten?
-- Wie wird so ein Schlüssel dann bei der Katalogisierung eingegeben?


Primärschlüssel


Gebraucht werden Primärschlüssel in allegro-Datenbanken beim Einspeisen
von Daten mit dem Programm UPDATE und genauso in a99 beim Einspeisen
mit dem FLEX-Befehl "update".
Will man neue Daten nicht ohne jede Rücksicht auf die vorhandenen
einfach als neue Sätze einfügen, sondern Dubletten vermeiden oder auch
vorhandene Datensätze gezielt verändern, muß das Programm wissen, wie
alte (= schon vorhandene) und neue Datensätze zusammengehören.

Als Primärschlüssel gilt bei  UPDATE  und  update  der erste Register-
eintrag, der beim Speichern eines Datensatzes gebildet wird. Damit
er dafür brauchbar ist, muß er eindeutig sein und er muß bei
hierarchischen Sätzen aus dem Hauptsatz gebildet werden, nicht aus
einem Untersatz. Er braucht nicht dem Inhalt einer bestimmten Kategorie
zu entsprechen (z.B. #00) und auch nicht für alle Satzarten nach den
gleichen Regeln konstruiert zu werden und im gleichen Register zu
erscheinen. Beispielsweise bekommen die Bestell- und Exemplarsätze, die
das Programm ORDER erzeugt, andere Primärschlüssel als die Titelsätze
der gleichen Datenbank.

Im Standardschema, mit Standard-Indexparametern, besteht aber der
Primärschlüssel eines Titelsatzes aus dem Inhalt der Kategorie #00,
evtl. umcodiert, im Register 9. Der erste Kopfbefehl lautet

ak=zz+@

Dieser Befehl wird immer ausgeführt, egal, welche Kategorien im Satz
belegt sind oder nicht; der Schlüssel wird also für jeden Satz bei der
Sprungmarke #-@ gebildet. Dies ist dann zwingend, wenn aLF oder ORDER
benutzt werden, aber es ist immer praktisch, so zu verfahren.
Der einfachste Primärschlüssel besteht aus dem unveränderten,
allenfalls umcodierten Inhalt einer bestimmten Kategorie, dann sieht
der Abschnitt für seine Erzeugung so aus:

#-@
!00 p"|9"
#+#

Hier wird #00 umcodiert, nicht weiter vorbehandelt und im
Register 9 indexiert.

Mehr zum Thema 'Primärschlüssel' im Systemhandbuch bei der Beschreibung
des Programms UPDATE (Abschnitt 9.3, S. 158f oder online: h ac9). Dort
ist auch ein etwas weniger schlichtes Beispiel vollständig ausgeführt.

Zwei Dinge noch in aller Deutlichkeit:
1. es gibt nicht DEN Primärschlüssel, d.h. er steht nicht in
   einem dafür festgelegten Feld, und
2. ein Primärschlüssel braucht keine Nummer zu sein.
In unterschiedlichen Situationen können unterschiedliche Schlüssel
die Primärrolle übernehmen. Dazu sind "nur" die entsprechenden
Eingriffe in die Indexparameter nötig. Beim FLEX-Befehl "update" kann
auch mit dem Befehl "set pX" ad hoc irgendein geeigneter Schlüssel
zum Primärschlüssel ernannt werden!  (mehr:  h xset  eingeben)


Automatische Nummernvergabe

Jede eindeutige Nummer, die in jedem Datensatz auftritt, KANN bei
Bedarf als Primärschlüssel dienen.
Nicht alle Datensätze besitzen "von Natur aus" ein Datenfeld, dessen
Inhalt immer vorhanden und eindeutig ist. Die interne Nummer eignet
sich nicht, weil sie veränderlich ist (s. Lektion 2.3, Verknüpfungskon-
zepte). Eine ISBN gibt es nicht immer und sie ist gelegentlich auch
nicht eindeutig. Signaturen werden u.U. erst spät im Geschäftsgang
vergeben, die Aufnahme soll aber vorher schon im Katalog stehen.
Außerdem können auch sie sich ändern. Zugangsnummern können für
mehrere Bücher gleich sein, z.B. für alle Bücher auf einer Rechnung.

Es wäre also praktisch, eine garantiert eindeutige Nummer für den Satz
zusätzlich zu erzeugen, und zwar per Programm. Relationale Datenbanken
haben dafür verschiedene Mechanismen: "Auto-increment"-Felder,
Generatoren u.ä.

allegro benutzt zwei Befehle in der Konfigurationsdatei, mit denen sehr
flexible Formen der Numerierung erreicht werden können; allerdings
kann jeder einzelne Datensatz nur eine automatisch vergebene Nummer
bekommen.

cg    Kategorie für automatische Nummernvergabe festlegen
Hinter cg steht eine Kategorienummer, sonst nichts. Meist wird cg00
gesetzt, zwingend ist das nicht. Die Kategorienummer gibt an, in
welcher Kategorie die Konstruktionsvorschrift für die automatische
Nummernvergabe zu finden ist. Ohne den Befehl  cg  wird keine Nummer
automatisch vergeben.

ci    Standardform der zu vergebenden Nummer
Wenn es einen Befehl cg gibt, und wenn die in diesem Befehl genannte
Kategorie in einem Satz nicht belegt ist, dann wird sie so belegt,
wie ci es vorschreibt. Die Angabe hinter ci muß diese Form haben:

Rabc?kABC

Dabei bedeuten

R    Nummer eines Registers (1-9 bzw. ':' für 10, ';' für 11)
abc    Beliebige Zeichen vor der Nummer
?k    Platzhalter für die Nummer, k ist eine Zahl
ABC    Beliebige Zeichen hinter der Nummer

Bis auf Registernummer und Fragezeichen kann alles fehlen, insbesondere
Zeichen hinter der Nummer sind selten sinnvoll. Im durch R gegebenen
Register muß der Kategorieinhalt indexiert werden, ggf. mit Prä- und
Postfix wie in ci angegeben. Dann wird im Augenblick des Speicherns der
bisher größte Eintrag der gegebenen Form ermittelt, die Zahl darin um 1
erhöht und bei Bedarf mit führenden Nullen auf k Stellen aufgefüllt.
Der so ermittelte Eintrag kommt in die durch cg angegebene Kategorie
des aktuellen Satzes. Wenn die Nummern-Kategorie nicht schon belegt
war, passiert dies auch beim Ändern eines Satzes, nicht nur bei
einem neuen Satz!

Achtung: die Konfigurationsdatei ist nicht für das Indexieren des neuen
Schlüssels im richtigen Register zuständig, das muß in den
Indexparametern separat festgelegt werden. Es ist Voraussetzung für die
Eindeutigkeit der automatisch vergebenen Nummern.

Nummernvergabe je nach Satztyp

Wirklich flexibel wird dieses Verfahren aber erst durch die Möglichkeit,
die durch cg vorgegebene Kategorie explizit zu belegen. Ein Eintrag,
der kein Fragezeichen enthält, wird gespeichert, wie er ist, eine
automatische Nummernvergabe findet in diesem Fall nicht statt.
Beim Ändern von Sätzen ist das der Normalfall, weil die Nummer meistens
schon da ist. Enthält die Kategorie aber ein Fragezeichen, dann wird
der Inhalt als Numerierungsvorschrift nach dem folgenden Schema
interpretiert (ganz ähnlich wie in ci):

#xzy |R#nnfabc?kABC

#xzy ist die in cg angegebene Kategorie (d.h. in der Konfiguration
steht "cgxzi"). |R ist das Register, in dem die letzte passende Nummer
gesucht und die neue indexiert werden soll. Wenn diese Angabe fehlt,
wird das Register aus  ci  genommen. #nnf ist eine gültige Kategorie-
nummer; wenn sie vorhanden ist, wird die neu vergebene Nummer nicht
in #xzy, sondern in #nnf gespeichert. Achtung: dann fehlt #xzy im
fertigen Satz und wird beim nächsten Ändern des Satzes zusätzlich
erzeugt, wie in ci vorgegeben. Wenn das nicht gewünscht wird, muß
es explizit verhindert werden (wie das geht, kommt weiter unten).
Der Rest des Kategorie-Inhalts wird genau so verarbeitet wie oben
beschrieben.

Beispiel:

In der Standardkonfiguration steht

cg00
ci9a?5

D.h. wenn #00 beim Speichern nicht schon belegt ist, dann kommt der
nächste Eintrag der Form "axxxxx" hinein, die Zahl xxxxx wird aus
Register 9 ermittelt und die Kategorie dort indexiert. Letzteres
muß, wie gesagt, in den Indexparametern geregelt sein.

Bestimmte Satztypen können aber andere Nummern kriegen, so steht z.B.
in einem Personenstammsatz im Augenblick des Speicherns

#00 p?4

d.h. dieser Satz bekommt die nächste vierstellige Nummer mit dem
Präfix p, diese Nummer wird aber ebenfalls in Register 9 indexiert,
wie es die Indexparameter für die #00 vorschreiben.

Erläutert wird die automatische Nummernvergabe im Systemhandbuch
bei den Konfigurationsbefehlen (Abschnitt A.1.3, Sonstige
Konfigurationsbefehle, S. 293, oder h aca-1).

Es liegt im übrigen zwar nahe, die automatische Nummernvergabe für
den Primärschlüssel zu nutzen, wenn ein solcher gebraucht wird.
Zwingend ist es aber nicht. Wenn es so sein soll, dann muß der erste
Schlüssel beim Abarbeiten der Indexparameter aus der automatisch
vergebenen Nummer entstehen, siehe oben.

Vorgaben für die Nummernvergabe in den einzelnen Satz bringen

Für Sätze, deren ID-Nummer genau dem Schema aus ci entsprechen soll,
ist gar nichts zu tun: die entsprechende Kategorie bleibt bei der
Eingabe leer. Für alle anderen Sätze wäre es lästig und fehlerträchtig,
jedesmal beispielsweise "p?4" in #00 schreiben zu müssen. Das Eintragen
fester Texte in beliebige Kategorien läßt sich über die Abfrageliste
oder in den Windows-Programmen über Eingabeformulare regeln:

In der Abfrageliste bringt eine Zeile der Form

xxf"Text"abc<

den Text "abc" in die Kategorie xxf. Das "<" sorgt dafür, daß der
Eintrag ohne <Enter> sofort übernommen wird, wenn die entsprechende
Stelle in der Abfrageliste abgearbeitet wird. Der zuständige Abschnitt
für einen Personenstammsatz würde also etwa so beginnen:

-p   Personenstammsatz
00 "     Id.Nr.: "p?4<

Ganz ähnlich im Eingabeformular: hier schreibt eine Zeile

<xxfabc

den Text "abc" in die Kategorie xxf, dank "<" wieder ohne
Benutzereingriff. Für den Personenstammsatz also

[Personenstammsatz]
<00 p?4

Schließlich kann die ID-Nummern-Kategorie auch noch im Flex onput.flx
belegt werden, oder auch im Hilfsabschnitt der Indexparameterdatei.

Wenn es darum geht, eine nachträgliche ID-Nummernvergabe beim Ändern
eines Datensatzes zu verhindern, dann eignen sich onput.flx und
Hilfsabschnitt besser als Abfrageliste und Eingabeformular, die beide
nicht unbedingt für jede Korrektur benutzt werden.
Jetzt muß der Eintrag so aussehen (cg00 vorausgesetzt):

#00 |9#75zabc?ixyz

Der Witz dabei ist, daß #75z eine UNgültige Kategorie sein muß. Dann
wird der Eintrag zwar erzeugt, aber nicht gespeichert, und #00 bleibt
leer. Nötig ist das in erster Linie für Sätze, die ihre ID-Nummern
anderswo haben als in der sonst dafür vorgesehenen Kategorie.

Erklärt wird das Einsetzen fester Texte mittels Abfrageliste im
Systemhandbuch (Abschnitt A.2, Abfrageliste, S. 296f oder h aca-2;
hier auch das Verhindern einer Nummernvergabe); Eingabeformulare sind
im gedruckten Handbuch nicht so ausführlich beschrieben wie im
zuständigen Online-Hilfetext (h form). Zum Hilfsabschnitt in den
Indexparametern s. Systemhandbuch, Abschnitt 10.2.8, Programmierte
Validierungen (Eingabeprüfung).