RecRead
Mit RecRead() sind verschiedene Zugriffsmöglichkeiten auf Datensätze realisiert.
Sofern keine Optionen in (int3) angegeben werden, ist das Verhalten folgendermaßen:
Dem Befehl werden die Datei (int1) und der Schlüssel (int2) übergeben. In dem Schlüssel sind die Felder des Datensatzes definiert, aus denen die Schlüsselwerte gebildet werden. Beim Zugriff auf einen Datensatz wird aus dem Inhalt dieser Felder der Schlüsselwert erstellt und in der Schlüsseltabelle gesucht. Anhand des erhaltenen Schlüssels wird dann ein Datensatz in den Standard-Datensatzpuffer geladen. Ist in (int1) ein Datensatzpuffer angegeben (siehe ``RecBufCreate()), wird dieser beim Laden verwendet.
Anstatt eines Schlüssels kann in (int2) auch der Deskriptor einer Selektion angegeben werden (siehe ``SelOpen()). Dabei muss sich die Hauptergebnismenge der Selektion auf die in (int1) angegebene Datei beziehen und die Selektionsmenge sperrend gelesen worden sein. Für einen Zugriff über die Datensatz-ID wird in (int2) 0, in (int3) _RecID und in (bigint4) die Datensatz-ID übergeben.
Mehrere Optionen können miteinander kombiniert werden. Die Kombination erfolgt durch eine binäre ODER-Verknüpfung.
Beispiel:
RecRead(Adr.D.Adressen, Adr.S.iNummer, _RecFirst | _RecLock);
Die Optionen in (int3) teilen sich in drei unterschiedliche Gruppen:
Lesen von Datensätzen
-
0Ausgehend vom Inhalt der Feldpuffer wird genau der angegebene Datensatz gelesen. Der Rückgabewert des Befehls ist dann abhängig, ob über einen eindeutigen oder mehrdeutigen Schlüssel gelesen wurde
_rOkoder_rMultiKey. Eine Satzsperre beeinflusst den Rückgabewert nicht. Konnte aus dem Inhalt der Schlüsselfelder kein vorhandener Schlüsselwert gebildet werden, wird der darauf folgende Datensatz gelesen. In diesem Fall gibt der Befehl den Wert_rNoKeyzurück. Gibt es keinen nachfolgenden Datensatz, wird der letzte Datensatz gelesen. Zurückgegeben wird dann der Wert_rLastRec. Konnte kein Datensatz gelesen werden (d. h. die Datei ist leer), wird der Wert_rNoReczurückgegeben. -
Der Satz mit dem kleinsten Schlüsselwert wird geladen.
-
Der Satz mit dem größten Schlüsselwert wird geladen.
-
Ausgehend vom Inhalt der Feldpuffer wird der Satz mit dem nächst größeren Schlüsselwert geladen. Sofern kein weiterer Satz vorhanden ist, wird als Resultat
_rNoReczurückgeliefert. -
Ausgehend vom Inhalt der Feldpuffer wird der Satz mit dem nächst kleineren Schlüsselwert wird geladen. Sofern kein weiterer Satz vorhanden ist, wird als Resultat
_rNoReczurückgeliefert. -
Die Schlüsselreihenfolge in der mit
_RecPrev,_RecNextund_RecPoszugegriffen wird, kann mit dieser Konstanten umgekehrt werden. -
Anstatt über einen Schlüssel wird der Datensatz über die Datensatz-ID gelesen. In (int2) darf kein Schlüssel oder Selektionsdeskriptor übergeben werden. Die Datensatz-ID wird entweder durch das aufgerufene Ereignis (wie zum Beispiel bei
EvtLstSelect) übergeben oder wurde zuvor mit der Anweisung RecInfo(..., _RecID)ermittelt. Im Parameter (bigint4) muss die zu lesende Datensatz-ID übergeben werden. -
Anstatt über den aktuellen Schlüsselwert wird über die Schlüsselposition zugegriffen (siehe ``RecInfo
()), die in (bigint4) übergeben werden muss. Diese Position wird aus nur ungefähr berechnet, da eine genaue Positionierung zu lange dauern würde.
Optional kann bei Verwendung von _RecPrev oder _RecNext in (int5) die Anzahl vorheriger bzw. nächsten Sätze angegeben werden, die gelesen werden sollen. Wird in (int5) beispielsweise 5 angegeben, wird in der Schlüsselfolge um 5 Sätze nach vorn bzw. zurück positioniert. Sind weniger Sätze als die angegebene Anzahl vorhanden, wird der erste bzw. der letzte Satz gelesen und das Resultat ist _rNoKey.
Beispiele:
// Lesen des Datensatzes mit der Nummer 1000
KND.iID # 1000;
tErg # RecRead(KND.D.Kunden, KND.S.ID, 0);
// Lesen des Datensatz mit der Nummer 1000, wenn ein Satzpuffer übergeben wird
tHdlBuf # RecBufCreate(KND.D.Kunden);
tHdlBuf->KND.iID # 1000;
tErg # RecRead(tHdlBuf, KND.S.ID, 0);
// Schleife über alle Datensätze
for tErg # RecRead(KND.D.Kunden, KND.S.ID, _RecFirst);
loop tErg # RecRead(KND.D.Kunden, KND.S.ID, _RecNext);
while (tErg < _rNoKey)
{
// Verarbeitung des Datensatzes
...
}
Sperroptionen
Wird keine Sperroption angegeben, so bleibt der Sperrstatus des gelesenen Satzes unverändert.
-
Der gelesene Satz wird entsperrt.
-
Der gelesene Satz wird gesperrt. Dies ist nur dann der Fall, wenn
_rOkzurückgeliefert wird (eindeutiger Schlüssel). Ist der Satz durch einen anderen Benutzer gesperrt, ist das Resultat_rLockedund der Datensatz wurde nicht gesperrt. Tritt beim Sperren eine Verklemmung auf, wird_rDeadlockzurückgegeben und der Datensatz wird nicht gesperrt. -
Der gelesene Satz wird gesperrt. Dies ist nur dann der Fall, wenn
_rOkzurückgeliefert wird (eindeutiger Schlüssel). Ist der Satz durch den eigenen oder einen anderen Benutzer gesperrt, ist das Resultat_rLocked. Das Sperren eines Datensatzes erfolgt über die Benutzer-ID. Mit dem Parameter_RecSingleLockwird der gleiche Datensatz für den gleichen Benutzer nur einmal gesperrt. Beim Versuch, denselben Satz ein zweites Mal zu sperren, wird das Resultat_rLockedzurückgeliefert. Diese Option muss in einer Applikation verwendet werden, in der zum Beispiel mehrere MDI-Fenster den gleichen Datensatz sperren können. Tritt beim Sperren eine Verklemmung auf, wird_rDeadlockzurückgegeben und der Datensatz wird nicht gesperrt. -
Der gelesene Datensatz wird gemeinsam mit anderen Benutzern gesperrt. Dies ist nur dann der Fall, wenn
_rOkzurückgeliefert wird (eindeutiger Schlüssel). Ist der Satz durch einen anderen Benutzer gesperrt, ist das Resultat_rLocked. Im Gegensatz zur Option_RecLockkönnen von anderen Benutzern weitere Sperren mit dieser Option eingerichtet werden. Ein mit_RecSharedLockgesperrter Datensatz kann von einem anderen Benutzer nicht mit der Option_RecLockzum Schreiben gesperrt werden, bis die letzte Sperre aufgehoben wurde. Der Benutzer, der die gemeinsame Sperre eingerichtet hat, kann den Datensatz nur dann mit_RecLocksperren, wenn in der Zwischenzeit kein anderer Benutzer eine gemeinsame Sperre eingerichtet hat. Mit dieser Option können mehrere Benutzer einen Datensatz vor Veränderung schützen. Der Datensatz kann mit dieser Sperre nicht zurückgeschrieben werden. Tritt beim Sperren eine Verklemmung auf, wird_rDeadlockzurückgegeben und der Datensatz wird nicht gesperrt. -
Der gelesene Satz wird gesperrt, ohne Rücksicht auf eine Sperre durch einen anderen Benutzer. Die Sperre ist nur dann erfolgt, wenn
_rOkzurückgeliefert wird. Wenn ein anderer Benutzer den Satz gesperrt haben sollte, kann dieser Benutzer den Satz nicht mehr zurückspeichern. Daher sollte_RecForceLocknur in den Fällen erfolgen, in denen ein Satz unbedingt und ohne Rücksicht auf andere Benutzer gesperrt werden muss. Die Sperre schlägt fehl, wenn der Datensatz durch andere Benutzer gemeinsam (_RecSharedLock) gesperrt ist oder der Datensatz in diesem Moment gerade geschrieben oder gelöscht wird. Wird_rLockedzurückgegeben, kann der Befehl nach kurzer Zeit erneut versucht werden. Tritt beim Sperren eine Verklemmung auf, wird_rDeadlockzurückgegeben und der Datensatz wird nicht gesperrt.infoFahrlässiger Umgang mit dieser Option kann zur Inkonsistenz des Datenbestandes führen.
-
Der Sperrstatus des Satzes wird überprüft. Das Resultat ist
_rLocked, wenn ein anderer Benutzer den Satz gesperrt hat, sonst_rOk. Der Sperrstatus wird nicht verändert.
Die Sperre eines Datensatzes wird an seiner Datensatz-ID festgehalten. D. h. es können alle Felder eines Datensatzes geändert werden, auch die des eindeutigen Schlüssels. Eine Änderung der Datensatz-ID zum Beispiel durch ``RecInfo(..., _RecIdSet,...), darf nicht erfolgen. Wurde Datensatz-ID geändert, gibt die Anweisung RecReplace() den Fehler _rNoLock zurück.
Wurde ein Datensatz gesperrt, bleibt er solange gesperrt, bis zum Beispiel die Anweisung RecRead(..., _RecUnlock) den Datensatz wieder entsperrt oder sich der Benutzer aus der Datenbank abmeldet. Werden Datensätze durch das Abmelden eines Benutzers entsperrt, kann sich das Abmelden entsprechend verzögern.
Beispiele:
// Datensatz mit der Nummer 1000 Lesen und sperren
fiCstID # 1000;
tErg # RecRead(tblCustomer, keyCstId, _RecLock);
...
// Datensatz wieder entsperren
tErg # RecRead(tblCustomer, keyCstId, _RecUnlock);
// Datensatz in einer MDI-Applikation sperren
tErg # RecRead(tblCustomer, keyCstId, _RecSingleLock);
// Ersten Datensatz sperren
tErg # RecRead(tblCustomer, keyCstId, _RecLock | _RecFirst);
Ladeoptionen
-
Hierbei erfolgt der Zugriff nur auf den Schlüssel. Es wird nicht auf den Datensatz zugegriffen, daher ist die Angabe einer Sperroption ohne Wirkung.
-
Der gelesene Datensatz wird nicht in die Feldpuffer übertragen.
Ist der angegebene Schlüsselwert vorhanden wird in beiden Fällen abhängig davon, ob über einen ein- oder mehrdeutigen Schlüssel zugegriffen wurde _rOk oder _rMultiKey zurückgegeben. Ist der Schlüsselwert nicht vorhanden, wird _rNoKey oder _rLastRec zurückgegeben. Je nachdem, ob es einen nachfolgenden Schlüsselwert gab oder nicht.
Beim Lesen eines Datensatzes mit diesen Ladeoptionen wird die Datensatz-ID nicht gesetzt. Vor einem Zurückschreiben des Satzes mit dem Befehl ``RecReplace() muss aber eine Datensatz-ID entweder durch Lesen des Datensatzes oder durch Setzen der ID mit dem Befehl RecInfo() vorhanden sein.
Beispiele
// Den Datensatz mit der Nummer 1000 sperren, ohne die anderen Feldpuffer zu überschreiben
fiCstID # 1000;
tErg # RecRead(tblCustomer, keyCstId, _RecLock | _RecNoLoad);
// Überprüfen, ob ein Schlüsselwert bereits existiert
fiCstID # 1000;
tErg # RecRead(tblCustomer, keyCstId, _RecTest);
Das Argument (bigint4) ist optional und hat drei verschiedene Bedeutungen:
-
Schlüsselposition
Bei Benutzung der Option
_RecPoswird in (bigint4) die gewünschte Schlüsselposition übergeben. -
Datensatz-ID
Ist (int2) gleich
0, wird in (bigint4) die ID des gewünschten Datensatzes übergeben. Die Datensatz-ID entspricht einem eindeutigen Schlüssel, der für interne Zwecke verwendet wird. Sie wird ebenfalls bei dem EreignisEvtLstSelectübergeben.Die Optionen
_RecTestund_RecPossowie die Angabe eines Schlüssels oder einer Selektion sind dabei nicht möglich, da kein Schlüsselzugriff erfolgt. Dadurch gibt es auch die Resultate_rNoKeyund_rMultiKeynicht.Ist der Datensatz mit der angegebenen ID nicht vorhanden, wird
_rNoReczurückgeliefert und kein Satz geladen.Wird eine Datensatz-ID angegeben, kann nicht mit den Optionen
_RecFirst,_RecLast,_RecNextoder_RecPrevzugegriffen werden. -
Filter-Deskriptor
Sofern weder
_RecPosnoch die Datensatz-ID verwendet wird, kann in (bigint4) der Deskriptor eines Filters angegeben werden (siehe RecFilterCreate()).
Resultate
Das Resultat von RecRead() kann durch die aufsteigenden Resultatwerte in den meisten Fällen durch einen Größer-/Kleiner-Vergleich ausgewertet werden:
// Feststellen ob ein Satz geladen wurde
if (RecRead(...) < _rNoRec)
{
...
}
Mögliche Laufzeitfehler:
_ErrNoFile: Datei nicht vorhanden_ErrNoKey: Schlüssel nicht vorhanden_ErrHdlInvalid: Filter- oder Selektions-Deskriptor ungültig_ErrNoArgument: Argument (bigint4) wird benötigt, fehlt aber