Index und Zugriff: Unterschied zwischen den Versionen

Aus Wiki des Deutschsprachige Xbaseentwickler e. V.
Zur Navigation springen Zur Suche springen
KKeine Bearbeitungszusammenfassung
KKeine Bearbeitungszusammenfassung
Zeile 137: Zeile 137:
  sowie ein Tag mit dem Namen "A1" angelegt;
  sowie ein Tag mit dem Namen "A1" angelegt;
  und der Index-Begriff wird mit "NACHNAME" festgelegt
  und der Index-Begriff wird mit "NACHNAME" festgelegt
== Zugriff auf indexierte Daten ==
Neben den unter Datenzugriff genannten Funktionen gibt es noch die Funktion dbSeek(), die ein gezieltes Suchen in einer indexierten Datei erlaubt.
// Annahme: der Index-Begriff ist Upper(NACHNAME), das Tag heisst "A1"
cKey := PadR("MEIER", 30)
lFound := dbSeek(cKey, .F., "A1", .F.)
Betrachten wir die Suchanweisung.
lFound wird mit einem logischen Wert belegt, der .T. ist, wenn ein Datensatz gefunden wurde, und .F., wenn kein passender Datensatz gefunden wurde.
cKey ist der Begriff, der gesucht werden soll. Anstelle einer Variablen kann auch ein Literal verwendet werden. In jedem Fall muss der Typ des Begriffs dem Index-Begriff entsprechen.
.F. besagt, dass wir einen exakten Treffer wollen. (siehe Softseek)
"A1" gibt an, dass der Tag "A1" verwendet werden soll. Es kann auch die Index-Position (bei mehreren aktiven Index-Dateien bzw. Tags) verwendet werden. Ist dieser Parameter leer (nicht angegeben), wird der aktive Index verwendet.
.F. besagt, dass er erste übereinstimmende Datensatz geliefert werden soll. Bei .T. wird der letzte übereinstimmende Datensatz geliefert, wenn es mehrere Datensätze gibt, welche den gleichen Schlüssel haben.
===Softseek===
Standardmässig wird auf exakte Übereinstimmung gesucht.
Unter den Programm-Schaltern gibt es SET SOFTSEEK, mit dem dieses Verhalten für den jeweiligen Thread gesteuert werden kann.
Der Parameter für Softseek hat Vorrang über dem Programm-Schalter SET SOFTSEEK.
{| class="wikitable"
|-
! Parameter !! SOFTSEEK !! gefunden !! Found() !! EoF()
|-
| .F.      || egal    || ja      || .T.    || .F.
|-
| .F.      || egal    || nein    || .F.    || .T.
|-
| .T.      || egal    || ja      || .T.    || .F.
|-
| .T.      || egal    || nein    || .F.    || .F.
|-
| NIL      || ON      || ja      || .T.    || .F.
|-
| NIL      || ON      || nein    || .F.    || .F.
|-
| NIL      || OFF      || ja      || .T.    || .F.
|-
| NIL      || OFF      || nein    || .F.    || .T.
|}
Nach der Positionierung mit dbSeek() kann mittels dbSkip() ab diesem Satz durch den Index manövriert werden.

Version vom 14. Mai 2013, 14:43 Uhr

Datenzugriff - warum?

Daten, die nicht ausgewertet werden können, haben wenig Wert in der Datenverarbeitung. Xbase++ bietet zwei grundsätzliche Zugriffsmethoden an:


in der Reihenfolge der Satzerstellung

Grob vereinfacht kann man eine dBase-Datei als einen Karteikasten betrachten, dessen Karten man in der Reihenfolge, in der sie in den Kasten gelegt wurden, auch lesen kann.

Der entsprechende Wert, nach dem die Datensätze gelesen werden, ist die sogenannte Satznummer. Der erste Satz hat die Satznummer 1, der zweite Satz die Satznummer 2, und so weiter.

Mit diesem Zugriffsmechanismus kann auch auf einen beliebigen Satz zugegriffen werden, wenn seine Satznummer bekannt ist.


in beliebiger (wahlfreier) Folge

Sortieren

Der klassische Weg wäre es, die Datensätze nach bestimmten Kriterien zu sortieren. Bei einer Einzelplatz-Anwendung mag ein solches Verfahren noch akzeptabel sein, wenn die Datenmenge nicht zu gross ist, aber ab einem bestimmten Datenvolumen, oder spätestens wenn wir mit Multithreading oder von mehreren Arbeitsplätzen in einem Netzwerk auf die Daten zugreifen, entfällt der Sort.

Nichtsdestotrotz gibt es heute immer noch einen Sort-Befehl im Sprachumfang von Xbase++.


Über einen Index

Ein Index ist - vereinfacht gesprochen - eine Liste, die einem bestimmten Such- oder Sortierkriterium die Nummer des Datensatzes zuweist, in dem eine Übereinstimmung mit dem Suchkriterium vorhanden ist.

Beispiel:

Müller  | Peter | (1)
Baumann | Klaus | (2)
Bender  | Erika | (3)
Adeno   | Rita  | (4)

Ein Index über den Nachnamen könnte (grob vereinfacht) so aussehen:

Adeno   | (4)
Baumann | (2)
Bender  | (3)
Müller  | (1)

Ein Programm, dass die Datei nach Kundenname lesen soll, liest den Index und greift dann über die Satznummer auf die eigentliche Datei zu. Wie gesagt, diese Darstellung ist grob vereinfacht.

Während SQL von Hause aus auf solche Zugriffe spezialisiert ist, müssen wir in Xbase++ einen solchen Index immer selbst erzeugen.

Für den Aufbau des Index und die interne Wartung des Index ist die Xbase++-Laufzeitumgebung verantwortlich, so dass wir uns darum nicht kümmern müssen.


Index-Arten

NDX

Die ursprünglichen Clipper-Indexdateien hatten die Erweiterung NDX und waren quasi der erste Wurf.

NTX

Spätere Clipper-Versionen brachten mit den NTX-Dateien eine verbesserte und robustere Variante auf den Markt, die auch heute noch von Xbase++ unterstützt wird.

Ursprünglich konnte eine NTX-Datei nur einen Index-Begriff unterstützen, dies ist jedoch inzwischen überholt, so dass mit einer NTX-Datei mehrere Index-Begriffe verwaltet werden können.

CDX

FoxPro brachte eine Erweitung der Index-Dateien, in dem CDX-Dateien als erste mehr als einen Index-Begriff verwalten konnten, und auch das "starre" Verhältnis von einem Datensatz zu einem Index-Satz aufgebrochen wurde durch die sogenannten "roll-your-own" Index-Dateien.


Struktur einer Index-Datei

Index-Datei

Darunter verstehen wir hier die physische, auf einem beliebigen Medium gespeicherte Datei. Der Name der Datei kann, muss aber nicht dem Namen der zugrundeliegenden dBase-Datei entsprechen. Viele Programmierer benennen die Index-Datei jedoch so, wie auch die dBase-Datei heisst.


TAG

Unter Tag (englisch, nicht der deutsche Tag) versteht man eine Kombination aus Index-Begriff und Zugriffsweg.

Eine NTX-Datei kann genau ein Tag enthalten, während eine CDX-Datei eine theoretisch unbeschränkte Anzahl Tags enthalten kann (wobei das Speichermedium auf der einen Seite und die Perfomance auf der anderen Seite deutliche Grenzen setzen können).


Index-Begriff

Der Index-Begriff beschreibt, aus welchen Feldern und/oder Funktionen sich der Such- bzw. Sortier-Begriff zusammensetzen soll.

Dieser Begriff muss in der Xbase++-Sprache sinnvoll auszuwerten sein.

Beispiel:

Dateiaufbau:
NACHNAME   | CHAR | 30
VORNAME    | CHAR | 30
STRASSE    | CHAR | 30
PLZ        | CHAR | 10
ORT        | CHAR | 40
KUNDNUMMER | NUM  | 10,0

Gültige Indexbegriffe wären:

NACHNAME+VORNAME
VORNAME+NACHNAME
PLZ+NACHNAME
KUNDNUMMER
Str(KUNDNUMMER)
Left(NACHNAME, 10)
NACHNAME+"PETER"

Ungültige Indexbegriffe wären:

NACHNAME+LAND (Land ist in der Datei nicht definiert)
ORT+KUNDNUMMER (alle Elemente im Index-Begriff müssen den gleichen Typ haben)


Zugriffsweg

Diesen Begriff habe ich aus einem Host-System übernommen. Es beschreibt die Reihenfolge der Schlüssel und die zugeordneten Satznummern, um auf die korrespondieren Datensätze zugreifen zu können.

Die Xbase++-Laufzeitumgebung übernimmt die Verwaltung und Aktualisierung des Zugriffsweges, sofern es nicht ein "roll-your-own" Index ist.


Erstellen einer Index-Datei

Ausgehend von dem obigen Beispiel würde eine Index-Datei so erstellt:

NTX:
INDEX ON NACHNAME TO KUNDEN
In diesem Fall wird eine Index-Date mit dem Namen "KUNDEN" (TO KUNDEN) angelegt;
sowie ein Tag mit dem Namen "KUNDEN" angelegt (implizit, da die TAG Anweisung fehlt);
und der Index-Begriff wird mit "NACHNAME" festgelegt
CDX:
INDEX ON NACHNAME TAG "A1" TO KUNDEN
In diesem Fall wird eine Index-Date mit dem Namen "KUNDEN" (TO KUNDEN) angelegt;
sowie ein Tag mit dem Namen "A1" angelegt;
und der Index-Begriff wird mit "NACHNAME" festgelegt


Zugriff auf indexierte Daten

Neben den unter Datenzugriff genannten Funktionen gibt es noch die Funktion dbSeek(), die ein gezieltes Suchen in einer indexierten Datei erlaubt.

// Annahme: der Index-Begriff ist Upper(NACHNAME), das Tag heisst "A1"
cKey := PadR("MEIER", 30)
lFound := dbSeek(cKey, .F., "A1", .F.)

Betrachten wir die Suchanweisung.

lFound wird mit einem logischen Wert belegt, der .T. ist, wenn ein Datensatz gefunden wurde, und .F., wenn kein passender Datensatz gefunden wurde.

cKey ist der Begriff, der gesucht werden soll. Anstelle einer Variablen kann auch ein Literal verwendet werden. In jedem Fall muss der Typ des Begriffs dem Index-Begriff entsprechen.

.F. besagt, dass wir einen exakten Treffer wollen. (siehe Softseek)

"A1" gibt an, dass der Tag "A1" verwendet werden soll. Es kann auch die Index-Position (bei mehreren aktiven Index-Dateien bzw. Tags) verwendet werden. Ist dieser Parameter leer (nicht angegeben), wird der aktive Index verwendet.

.F. besagt, dass er erste übereinstimmende Datensatz geliefert werden soll. Bei .T. wird der letzte übereinstimmende Datensatz geliefert, wenn es mehrere Datensätze gibt, welche den gleichen Schlüssel haben.


Softseek

Standardmässig wird auf exakte Übereinstimmung gesucht.

Unter den Programm-Schaltern gibt es SET SOFTSEEK, mit dem dieses Verhalten für den jeweiligen Thread gesteuert werden kann.

Der Parameter für Softseek hat Vorrang über dem Programm-Schalter SET SOFTSEEK.

Parameter SOFTSEEK gefunden Found() EoF()
.F. egal ja .T. .F.
.F. egal nein .F. .T.
.T. egal ja .T. .F.
.T. egal nein .F. .F.
NIL ON ja .T. .F.
NIL ON nein .F. .F.
NIL OFF ja .T. .F.
NIL OFF nein .F. .T.

Nach der Positionierung mit dbSeek() kann mittels dbSkip() ab diesem Satz durch den Index manövriert werden.