Zum Hauptinhalt springen

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

  • 0

    Ausgehend 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 _rOk oder _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 _rNoKey zurü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 _rNoRec zurückgegeben.

  • _RecFirst

    Der Satz mit dem kleinsten Schlüsselwert wird geladen.

  • _RecLast

    Der Satz mit dem größten Schlüsselwert wird geladen.

  • _RecNext

    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 _rNoRec zurückgeliefert.

  • _RecPrev

    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 _rNoRec zurückgeliefert.

  • _RecKeyReverse

    Die Schlüsselreihenfolge in der mit _RecPrev, _RecNext und _RecPos zugegriffen wird, kann mit dieser Konstanten umgekehrt werden.

  • _RecID

    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.

  • _RecPos

    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.

  • _RecUnlock

    Der gelesene Satz wird entsperrt.

  • _RecLock

    Der gelesene Satz wird gesperrt. Dies ist nur dann der Fall, wenn _rOk zurückgeliefert wird (eindeutiger Schlüssel). Ist der Satz durch einen anderen Benutzer gesperrt, ist das Resultat _rLocked und der Datensatz wurde nicht gesperrt. Tritt beim Sperren eine Verklemmung auf, wird _rDeadlock zurückgegeben und der Datensatz wird nicht gesperrt.

  • _RecSingleLock

    Der gelesene Satz wird gesperrt. Dies ist nur dann der Fall, wenn _rOk zurü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 _RecSingleLock wird der gleiche Datensatz für den gleichen Benutzer nur einmal gesperrt. Beim Versuch, denselben Satz ein zweites Mal zu sperren, wird das Resultat _rLocked zurü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 _rDeadlock zurückgegeben und der Datensatz wird nicht gesperrt.

  • _RecSharedLock

    Der gelesene Datensatz wird gemeinsam mit anderen Benutzern gesperrt. Dies ist nur dann der Fall, wenn _rOk zurückgeliefert wird (eindeutiger Schlüssel). Ist der Satz durch einen anderen Benutzer gesperrt, ist das Resultat _rLocked. Im Gegensatz zur Option _RecLock können von anderen Benutzern weitere Sperren mit dieser Option eingerichtet werden. Ein mit _RecSharedLock gesperrter Datensatz kann von einem anderen Benutzer nicht mit der Option _RecLock zum Schreiben gesperrt werden, bis die letzte Sperre aufgehoben wurde. Der Benutzer, der die gemeinsame Sperre eingerichtet hat, kann den Datensatz nur dann mit _RecLock sperren, 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 _rDeadlock zurückgegeben und der Datensatz wird nicht gesperrt.

  • _RecForceLock

    Der gelesene Satz wird gesperrt, ohne Rücksicht auf eine Sperre durch einen anderen Benutzer. Die Sperre ist nur dann erfolgt, wenn _rOk zurückgeliefert wird. Wenn ein anderer Benutzer den Satz gesperrt haben sollte, kann dieser Benutzer den Satz nicht mehr zurückspeichern. Daher sollte _RecForceLock nur 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 _rLocked zurückgegeben, kann der Befehl nach kurzer Zeit erneut versucht werden. Tritt beim Sperren eine Verklemmung auf, wird _rDeadlock zurückgegeben und der Datensatz wird nicht gesperrt.

    info

    Fahrlässiger Umgang mit dieser Option kann zur Inkonsistenz des Datenbestandes führen.

  • _RecCheckLock

    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.

info

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

  • _RecTest

    Hierbei erfolgt der Zugriff nur auf den Schlüssel. Es wird nicht auf den Datensatz zugegriffen, daher ist die Angabe einer Sperroption ohne Wirkung.

  • _RecNoLoad

    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 _RecPos wird 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 Ereignis EvtLstSelect übergeben.

    Die Optionen _RecTest und _RecPos sowie die Angabe eines Schlüssels oder einer Selektion sind dabei nicht möglich, da kein Schlüsselzugriff erfolgt. Dadurch gibt es auch die Resultate _rNoKey und _rMultiKey nicht.

    Ist der Datensatz mit der angegebenen ID nicht vorhanden, wird _rNoRec zurückgeliefert und kein Satz geladen.

    Wird eine Datensatz-ID angegeben, kann nicht mit den Optionen _RecFirst, _RecLast, _RecNext oder _RecPrev zugegriffen werden.

  • Filter-Deskriptor

    Sofern weder _RecPos noch 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: