Herbert Mueller: Records editieren in Flat-File DB

Hallo zusammen,

ich möchte folgendes Problem lösen:

1.

Wie kann ich einen spezifischen Datensatz aus einer
Flat-File-Datanbank in eine editierbare Tabelle abfüllen?

Mein eigentliches Problem ist, dass ich es wohl fertigbringe, einen Datensatz aus der DB auszulesen, doch WIE kann ich den betreffenden Record so markieren, dass er nach der Bearbeitung im Formular wieder zurückgeschrieben werden kann?

Kann er überhaupt zurückgeschrieben werden?

Wie funktioniert dieser Mechanismus genau?

Wer kann mir weiterhelfen?

Für Eure Bemühungen danke ich Euch bereits im voraus.

Herzliche Grüsse,

Herbert Müller

  1. hallo, nochmal ich

    beim erzeugen des datensatzes schreibst du zusätzlich zum dem datensatz noch eine eindeutige zahl, mit der du einen datensatz ansprechen kannst. in der datentechnik heißt so etwas eindeutiger künstlicher id-key. bei personen wäre das z.b. die reisepaß-nummer: jeder hat eine ganz eigene. in perl kannst du beim erzeugen die funktion time verwenden, sie gibt die anzahl der sekunden seit 1980 (glaub ich) aus. beim ausgeben des datensatzes kannst du dieses zahl im formular als hidden field übernehmen, beim abschicken kannst du nun den datensatz eindeutig finden.

    1. in perl kannst du beim erzeugen die funktion time verwenden, sie gibt die anzahl der sekunden seit 1980 (glaub ich) aus. beim ausgeben des datensatzes kannst du dieses zahl im formular als hidden field übernehmen, beim abschicken kannst du nun den datensatz eindeutig finden.

      ... wenn der Rechner langsam genug war, nicht mehrere INSERTs pro Sekunde zu verarbeiten ...

  2. Hallo Herbert

    Wie kann ich einen spezifischen Datensatz aus einer
    Flat-File-Datanbank in eine editierbare Tabelle abfüllen?

    Falls Du die Perl-Module DBI und DBD-CSV für den Datenbankzugriff verwendest, dann kannst Du in der (fast) gleichen Art und Weise auf die Datensätze in Deiner Flat-File-DB zugreifen, wie auf einen SQL-Server. Es stehen Dir die gleichen SQL-Statements (SELECT, INSERT, UPDATE, DELETE, ...) zur Verfügung.

    Mein eigentliches Problem ist, dass ich es wohl fertigbringe, einen Datensatz aus der DB auszulesen, doch WIE kann ich den betreffenden Record so markieren, dass er nach der Bearbeitung im Formular wieder zurückgeschrieben werden kann?

    Wie gerhard beschrieben hat, hängt das nicht mit der Technik des Datenzugriffs zusammen, sondern mit der Datenmodellierung.
    Für die eindeutige Identifizierung eines Datensatzes benötigst Du eine Feld (Tabellenspalte) mit der ID, die Du für jeden Datensatz erzeugen musst. Die ID wird mit dem SELECT-Statement ausgelesen und wird beim zurückschreiben der geänderten Formulardaten in der WHERE-Klausel des UPDATE-Statements wieder eingesetzt.
    Beispiel:
       SELECT id, feld1, feld2, feld3 FROM tabelle
    Die id schreibst Du in ein Hidden-Field des Formulars, damit sich beim Absenden des Formulars Deinem Skript wieder zur Verfügung steht.
    Die Änderungen schreibts Du dann mit dem UPdate-Statement wieder in die DB:
      UPDATE tabelle SET feld1=$in{'feld1'}, feld2=$in{'feld2'}, feld3=$in{'feld3'} WHERE id=$in{'id'}
    Der Hash %in enthält alle Formularfeldwerte, wie sie unter Verwendeung der cgi-lib.pl zur Vefügung gestellt werden.

    Falls die Anwendung in einer Mehrbenutzerumgebung läuft, in der mehr als ein Benutzer gleichzeitig Datensätze _ändern_ darf, so muss beim Aktualisieren des Datensatzes geprüft werden, ob nicht in der Zwischenzeit der Datensätz von jemand anderem geändert wurde, bzw. der Datensatz muss während der Bearbeitung durch einen Benutzer gesperrt bleiben.

    Dazu gibt es (grob, neben einigen anderen) 3 Möglichkeiten:

    • Du sperrst die ganze Tabelle, sobald ein User den Datensatz zum Ändern gelesen hat. Dies sollte über flock() (File-Locking in Perl) funktionieren. Wenn selten mehrere User auf die Tabelle zugreifen, ist das ok.
    • Du sperrst den zum Bearbeiten geladen Datensatz über Record-Locking. Dies muss jedoch von der DB-Engine unterstützt werden. MS Access und MS-SQL bieten etwas ähnliches unter Page-Locking. Dabei wird die interne Speicherseite (2048 Bytes) mit dem Datensatz gesperrt. Es werden also auch einige andere Datensätze in der "Umgebung" mitgesperrt. Das DBI-Modul und der DBD-CSV-Treiber für Flat-File-Tabellen unterstützt jedoch kein Sperren von Datensätzen oder ähnlichem.
    • Du fügst der Tabelle ein weiteres Feld hinzu, in dem bei jeder Änderung (Erstellen + Aktualisieren) des Datensatz ein Zeitstempel (timestamp) eingetragen wird. Dieser Zeitstempel kann tatsächlich ein Datums-/Zeitwert sein, kann jedoch auch ein serverinterner Zähler sein, der  bei jedem Prozessaufruf um eins hochgezahlt wird. Für nicht zu viele Änderungeszugriffe bietet sich in Perl die UTC-Zeit des Servers als Zeitstempel an. Sie wird durch $time ausgelesen und stellt die Anzahl Sekunden seit 1.1.1970 dar. Sind jedoch 2 oder mehr Aktualisierungszugriffe auf die Tabelle zu erwarten, so müssste die UTC-Zeit noch mit der Prozess-ID verknüpft werden (z.B. $time.$$). Auf jeden Fall wird bei jedem SELECT_Statement der Zeitstempel mit ausgelesen und im Formular in einem Hidden-Field zwischengespeichert. Beim Zurückschreiben der Änderungen überprüfst Du jedoch zuerst, ob der Zeitstempel im Datensatz sich verändert hat. Ist dies der Fall, so musst Du dem User eine Konfliktbehandlung anbieten. Andernfalls kannst Du die Änderung in die DB zurückschreiben.

    Beispiel:
       SELECT id, feld1, feld2, feld3, timestamp FROM tabelle
    Den timestamp schreibst Du in ein Hidden-Field des Formulars.

    Beim Abarbeiten der Formularrückgabe in deinem Skript liest Du den Zeitstempel nochmals aus:
      SELECT timestamp FROM tabelle
    und vergleichst Ihn mit dem Zeistempel im %in-Hash (z.B. $in{'timestamp'})
    Falls die Werte gleich sind, kannst Du die Änderungen in die DB schreiben.
      UPDATE tabelle SET feld1=$in{'feld1'}, feld2=$in{'feld2'}, feld3=$in{'feld3'}, timestamp=$time WHERE id=$in{'id'}
    wobei hier mit $time ein neuer Zeitstempel gesetzt wird.
    Bei hoher Aktualisierungshäufigkeit müsste zwischen dem 2. SELECT-Statement (bei auslesen des Zeitsstempels) und dem Zurückschreiben der Änderungen die Tabelle, bzw. der Record gesperrt werden.

    Ich hoffe, mit diesen Ausführungen nicht zuviel Verwirrung gestiftet zu haben.
    Wenn doch, dann kannst Du das Problem nochmals näher schildern.

    Grüsse
    Tom