Datensatz-ID Speicherung

Datenbank Bits

Wie bereits im Artikel Version 5.8 Teil 1 RecID unlimited angekündigt, stellt dieser Artikel Lösungsansätze für die Anpassung von Datensatz-IDs vor, wenn diese als Referenz auf einen Zieldatensatz gespeichert werden.

Hintergrund

Mit der Version 5.8 wurden die 64-Bit Datensatz-IDs eingeführt. Dadurch unterscheiden sich die IDs von Datensätzen zwischen der Version 5.7 und 5.8. Der vorliegende Artikel beschreibt, was beim Umstieg auf die Version 5.8 zu berücksichtigen ist, wenn eine Anwendung Datensatz-IDs persistent speichert um damit Daten zu referenzieren.
Beispiel

Mit der Version 5.7 wird eine Tabelle erstellt und anschließend ein Datensatz eingefügt. Anschließend wird der Datensatz gelesen und die Datensatz-ID (dezimal und hexadezimal) im Debugger ausgegeben:

@A+
@C+
main
{
  RecRead(100,1,0);
  DbgTrace('Version: ' + CnvAI(DbaInfo(_DbaClnRelMaj)) + '.' +
                         CnvAI(DbaInfo(_DbaClnRelMin)) +
           ' - Datensatz-ID: ' + CnvAI(RecInfo(100,_RecID)) +
           ' / 0x' + CnvAI(RecInfo(100,_RecID),_FmtNumHex | _FmtNumLeadZero,0,8));
}

Die folgende Zeile präsentiert das Ergebnis:

Version: 5.7 - Datensatz-ID: 16.777.216 / 0x01000000

Bei Ausführung mit der Version 5.8 ergibt sich das folgende Resultat:

Version: 5.8 - Datensatz-ID: 1 / 0x00000001

Die ermittelte Datensatz-ID unterscheidet sich also zwischen den Versionen. Da die Datensatz-ID in den meisten Fällen nur temporär verwendet wird, stellt das auch kein Problem dar. Anders verhält es sich jedoch, wenn die Datensatz-ID z.B. als Feld im Datensatz gespeichert wird, um damit einen bestimmten Datensatz einer anderen Tabelle zu referenzieren (Abb.1).

Referenzierung eines Datensatzes über seine Datensatz-IDAbb.1: Referenzierung eines Datensatzes über seine Datensatz-ID

Im Beispiel ist die Datensatz-ID als Feld in der Quelltabelle enthalten. Ein RecRead() über die gespeicherte Datensatz-ID in der Quelltabelle (z.B. RecID1) zur Ermittlung des Datensatzes in der Zieltabelle würde mit Version 5.8 ins Leere laufen, da jetzt seine Datensatz-ID eine andere ist (roter gestrichelter Pfeil).

Lösungsansatz

Der Ansatz besteht darin, aus der Datensatz-ID (Version 5.7) eine Datensatz-ID (Version 5.8) zu berechnen. Somit würde aus dem Wert 0x01000000 wieder 0x00000001, aus 0x02000000 wieder 0x00000002 usw. Die Referenz wäre auf diese Weise wiederhergestellt. Eine Funktion zum Berechnen der Datensatz-ID aus einem int-Wert zeigt der folgende Code:

// Konvertiert eine RecID, die in einem int-Wert abgelegt ist
sub ConvertSingleRecIDInt
(
  aRecID                : int;   // Datensatz-ID (Version 5.7)
  aTarTblIsSequential   : logic; // Zieldatei (auf die die RecIDs verweisen)
                                 // hat "sequentielles Einfügen" aktiviert?
)
: int;                           // Datensatz-ID (Version 5.8)
{
  if (aTarTblIsSequential)
  {
    if (aRecID & 0x80 != 0)
      ErrSet(_ErrValueOverflow);
    else
      return (
          (aRecID & 0xFF000000) >> 24 & 0xFF |
          (aRecID & 0x00FF0000) >> 8         |
          (aRecID & 0x0000FF00) << 8         |
          (aRecID & 0x000000FF) << 24
      );
  }
  else
  {
    if (aRecID > 0)
      ErrSet(_ErrValueOverflow);
    else
      return -aRecID;
  }
}

Die Funktion wandelt eine Datensatz-ID Version 5.7 (1. Argument) in eine Datensatz-ID Version 5.8 um (Rückgabewert). Je nachdem, ob die Option “Sequentielles Einfügen” bei der Zieltabelle gesetzt ist oder nicht, vergibt der Datenbank-Server die Datensatz-IDs in einer anderen Reihenfolge. Die Berechnung unterscheidet sich dann ebenfalls. Ist “Sequentielles Einfügen” bei der Tabelle gesetzt, wird der Funktion im zweiten Argument true übergeben, sonst false. Die Funktion setzt den globalen Fehlercode _ErrValueOverflow, wenn die resultierende Datensatz-ID >= 0x80000000 ist, da diese nicht im Wertebereich von int abgebildet werden können. Die Funktion sollte also nur verwendet werden, wenn der Prime-Counter der Zieldatei < 0x80000000 ist. Ist er größer, dann sollte die folgende Funktion verwendet werden:

// Konvertiert eine RecID, die in einem bigint-Wert abgelegt ist
sub ConvertSingleRecIDBigInt
(
  aRecID                : bigint; // Datensatz-ID (Version 5.7)
  aTarTblIsSequential   : logic;  // Zieldatei (auf die die RecIDs verweisen)
                                  // hat "sequentielles Einfügen" aktiviert?
)
: bigint;                         // Datensatz-ID (Version 5.8)
{
  if (aTarTblIsSequential)
  {
    return (
        (aRecID & 0x00000000FF000000\b) >> 24\b |
        (aRecID & 0x0000000000FF0000\b) >> 8\b  |
        (aRecID & 0x000000000000FF00\b) << 8\b  |
        (aRecID & 0x00000000000000FF\b) << 24\b)
    ;
  }
  else
  {
    if (aRecID < 0\b)
      return -aRecID;
    return (0x100000000\b - aRecID);
  }
}

Da der Rückgabewert der Funktion bigint ist, sind alle umzurechnenden Datensatz-IDs darstellbar. Dies bedeutet jedoch auch, dass für die Speicherung der Datensatz-ID nun ein bigint-Feld vorgesehen werden muss.

Die Funktion ConvertRecID58

Sofern die Datensatz-ID in einem Datenbankfeld gespeichert ist, reicht die Berechnung der Datensatz-ID alleine nicht aus. Die ursprüngliche Datensatz-ID muss auch durch den neuen Wert ersetzt werden:

  • On-demand
    Die Datensatz-ID wird ersetzt, wenn diese das erste Mal benötigt wird. Dies hat zum Vorteil, dass nicht alle gespeicherten Datensatz-IDs ersetzt werden müssen, sondern nur jene, die auch tatsächlich referenziert werden. Nachteil ist, dass alle Stellen im Quelltext angepasst werden müssen, wo auf die ursprüngliche Datensatz-ID zugegriffen wird. Des Weiteren wäre ein zusätzliches Flag im Datensatz notwendig, damit hervorgeht, ob die Datensatz-ID bereits umgerechnet wurde oder nicht.
  • Alle Datensätze
    Die Datensatz-IDs aller Datensätze wird berechnet und im Datensatz geändert. Der Vorteil hierbei ist, dass bei Verwendung desselben Datenbankfeldes für die neue Datensatz-ID keine Änderungen am Quelltext notwendig sind. Jedoch muss ein separater Durchlauf erfolgen, der einmalig alle Datensätze liest, die neue Datensatz-ID im Datenbankfeld einträgt und anschließend den Datensatz in der Datenbank aktualisiert.

Für die praktische Umsetzung der zweiten Methode kann die Funktion ConvertRecID58 verwendet werden:

sub ConvertRecID58
(
  aTblNo                : int;          // Tabellennummer in der die RecIDs stehen
  aSbrNoSrc             : int;          // Teildatensatznummer in aTblNo (Konvertierungsquelle)
  aFldNoSrc             : int;          // Feldnummer in aSbrNo (Konvertierungsquelle)
  aTarTblIsSequential   : logic;        // Zieldatei (auf die die RecIDs verweisen) hat "sequentielles Einfügen" aktiviert?
  opt aSbrNoTar         : int;          // Teildatensatznummer in aTblNo (Konvertierungsziel). Wenn nicht angegeben, wird aSbrNoSrc verwendet.
  opt aFldNoTar         : int;          // Feldnummer in aTblNo (Konvertierungsziel). Wenn nicht angegeben, wird aSbrNoSrc verwendet.
)

Die Funktion liest nacheinander alle Datensätze der Datei aTblNo und aktualisiert die Datenätze mit der neu berechneten Datensatz-ID. Das Feld, welches die Datensatz-ID (Version 5.7) speichert, wird über die Argumente aTblNo, aSbrNoSrc (Teildatensatznr.) und aFldNoSrc (Feldnr.) angegeben. Es muss den Datentyp int oder bigint besitzen. Wird nichts weiter angegeben, dann wird die Datensatz-ID im selben Feld gespeichert. Soll die Original-Datensatz-ID erhalten bleiben, kann über aSbrNoTar und aFldNoTar ein abweichendes Datenbankfeld im selben Datensatz angegeben werden.

Beispiel-Datenbank

Anhand der Beispiel-Datenbank am Ende des Blog-Artikels haben Sie die Möglichkeit, die beschriebene Funktion zu testen. Die Datenbank enthält berühmte Filmpaare. Eine Anleitung zur Verwendung des Beispiels befindet sich im Dokument ReadMe.rtf, das ebenfalls im Archiv enthalten ist.

Download

Beispiel-Datenbank FamousCouples.zip (70.94 KB)
Sie müssen angemeldet sein, um die Datei herunterladen zu können.

Klicken Sie hier, um die Nutzungsbedingungen für unseren Blog zu lesen.

Schreiben Sie einen Kommentar

Ihre E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Leave the field below empty!

Wünsche, Fragen oder Feedback sind willkommen:

Nutzungsbedingungen der Kommentarfunktion im Blog

1. Allgemeines

Vectorsoft AG („Anbieter“) stellt für Internetnutzer („Nutzer“) auf der Website
vectorsoft.de einen öffentlichen Blog bereit. Der öffentliche Blog dient dem
Informations- und Gedankenaustausch. Die Nutzer, welche sich mit Beiträgen und
Kommentaren beteiligen, verpflichten sich dazu, die Blog-Nutzungsbedingungen
einzuhalten und tragen die Verantwortung für die Richtigkeit und Angemessenheit
sowie Freiheit von Rechtsverletzungen ihrer Beiträge. Mit Nutzung der
Kommentarfunktion in unserem Blog akzeptieren Sie diese Nutzungsbedingungen.

2. Netiquette

Wir bitten Sie von persönlichen Angriffen und Provokationen aufgrund anderer
Meinungen abzusehen. Bitte argumentieren Sie sachlich und bewegen Sie sich auf
der Basis einer konstruktiven Diskussionskultur. Ihr Kommentar sollte stets im
Zusammenhang mit dem jeweiligen Thema sein, um Ausschweifungen in andere
Themenbereiche zu vermeiden. Das mehrmalige Posten desselben Kommentars
oder mehrerer ähnlicher Kommentare ist nicht erlaubt.

3. Verbot rechtswidriger Inhalte

Mit Absenden Ihres Kommentars bestätigen Sie, dass Sie keine Urheberrechte oder andere Rechte Dritter verletzen. Volksverhetzende, rassistische Äußerungen, Anleitungen zu Straftaten und deren Verherrlichung, Gewaltdarstellungen, pornografische Inhalte und Äußerungen, die Persönlichkeitsrechte verletzen sind untersagt.

4. Keine Werbung

Die Nutzung der Kommentarfunktion ist für kommerzielle oder parteipolitische
Zwecke nicht erlaubt. Werbliche Beiträge aller Art werden von uns umgehend
gelöscht.

5. Angaben zum Namen

Bei der Eingabe Ihres Namens achten Sie auf die zuvor genannten Grundsätze.

6. Quellenangaben

Bitte geben Sie bei der beabsichtigten Veröffentlichung von Zitaten oder Beiträgen
Dritter die jeweiligen Quellen an und erläutern dessen Bezug zum Blogbeitrag.

7. Verstoß gegen die Nutzungsbedingungen

Beiträge, die gegen diese Richtlinie verstoßen werden umgehend gelöscht. Sollten
Sie selbst Verstöße bemerken, so senden Sie uns bitte den Link des betreffenden
Kommentars per E-Mail an . Wir weisen ausdrücklich daraufhin, dass wir einzelne Nutzer bei wiederholten oder schweren Verstößen gegen diese
Nutzungsbedingungen ausschließen werden.

Stand: Sept. 2024

Deine Trial Version - jetzt anfordern!

Teste yeet - unverbindlich und kostenfrei

IHRE EVALUIERUNGSLIZENZ - JETZT ANFORDERN!

TESTEN SIE DIE CONZEPT 16 VOLLVERSION - UNVERBINDLICH und KOSTENFREI

Melden Sie sich bei unserem Newsletter an

Anrede*
     
Zustimmung zur Datenverarbeitung gem. DSGVO*



WordPress Cookie-Hinweis von Real Cookie Banner