Neuigkeiten:

Wenn ihr euch für eine gute Antwort bedanken möchtet, im entsprechenden Posting einfach den Knopf "sag Danke" drücken!

Mobiles Hauptmenü

Historische Datenhaltung

Begonnen von MartinHan, Januar 25, 2025, 14:56:53

⏪ vorheriges - nächstes ⏩

MartinHan

Hallo Klaus,

ob das alles klappt weiß ich auch noch nicht. Aber die Idee ist, das man auf Knopfdruck nachvollziehen kann, wer welche Kurse in der Vergangenheit besucht hat. Aktuell wird ja immer nur der aktuelle Stand gespeichert, die Historie ist weg.
Natürlich könnte ich selbst etwas basteln, aber wenn die DB das für mich abnimmt, find ich das besser.
Und eins habe ich von dir nicht verstanden, warum soll ich einen neuen Personensatz erzeugen, wenn jemnand umzieht? Per heute wird die neue Adresse eingetragen und fertig. Wo der Mensch vorher gewohnt hat, könnte man natürlich aus alten Sicherungen rausfinden, wäre aber dpch etwas umständlich.
Wenn man deiner Philosophie folgt, hast du natürlich recht, dann brauchte man die Hitorie nicht.

Ich werde berichten ab es klappt oder nicht und danke für deinen Beitrag.

Martin
Es gibt nichts gutes, außer, man tut es! EK

MzKlMu

#16
Hallo,
ZitatAber die Idee ist, das man auf Knopfdruck nachvollziehen kann, wer welche Kurse in der Vergangenheit besucht hat.
Und genau darum sollte eine normalisierte Struktur angelegt werden.
ZitatUnd eins habe ich von dir nicht verstanden, warum soll ich einen neuen Personensatz erzeugen, wenn jemnand umzieht?
Aber genau das willst Du doch mit der Historie machen. Dann kannst Du doch gleich bei Umzug einen neuen Datensatz anlegen. Außerdem könnte es durchaus wichtig sein zu wissen, wo jemand vorher gewohnt hat. Und bei Umzug würde man auch keinen neuen Personendatensatz anlegen, sondern nur einen weiteren Datensatz für die Adresse.

Mit Deinem Wunsch eine Historie anzulegen, machst Du genau das was Du in der Datenbank vermeiden willst. Und historiche Daten hast Du bis jetzt auch noch nicht. Warum dann nicht gleich die DB so gestalten, dass sich die Historie automatisch ergibt. Ändern musst Du sowieso.

Ich halte solche Historietabellen für ersatzlos überflüssig, wenn die Datenbank entsprechend gestaltet wird.
Gruß Klaus

MartinHan

Hallo Klaus,

man kann das so machen, also die Adressen in einer eigenen Tabelle speichen, wenn dann jemand umzieht kriegt die Person einen neuen FK. Bei mir ist eben die Adresse hart bei der Person.
Aber ob ich jetzt einen neuen Satz in der Adresstabelle anlege oder einen historische Satz anlege, ich denke der Unterschied sind ein paar Bytes...
bei den Personen ist das auch alles noch einfach, aber wenn es in die etwas kompxeren Beziehunge geht, gerät man leicht ins Unterholz...
So Cod may help...
Es gibt nichts gutes, außer, man tut es! EK

MzKlMu

Hallo,
Zitatwenn dann jemand umzieht kriegt die Person einen neuen FK.
Nein, so rum nicht. Wenn der FK in die Person kommt, ist die Historie weg. Die Adresse bekommt einen FK zur Person.
Zitataber wenn es in die etwas kompxeren Beziehunge geht, gerät man leicht ins Unterholz...
Aber mit Deinen Historietabellen doch erst recht. Du musst ja auch für die Historietabellen Beziehungen anlegen,  und die entsprechenden Inhalte die sich über die Fremdschlüssel ergeben ggf. mit in diese Historietabellen verschieben. Das gibt doch alles ein ziemliches Chaos mit neuen Bezeihnugen für die Historietabellen. Und wenn Du das nicht machst (mit den Beziehungen), hast Du in den Historietabellen zusammenhangslose Daten stehen.
Die Historietabellen sind nach meiner Auffassung eine Sackgasse und viel zu umständlich.
Gruß Klaus

PhilS


Zitat von: MartinHan am Januar 28, 2025, 11:43:39Aktuell wird ja immer nur der aktuelle Stand gespeichert, die Historie ist weg.
Das ist doch für die Kursteilnahme organisatorisch gar nicht wirklich möglich. Wenn deine Historie dafür "weg" ist, dann schießt du dir hier mit aller Gewalt selbst ins Bein.

Zitat von: MartinHan am Januar 25, 2025, 22:41:41Einige Kurse gibt es schon seit 30 Jahren!
Die Schüler melden sich an und bleiben für unbestimmte Zeit in dem Kurs bis sie kündigen oder der Kurs mangels Masse aufgelöst wird, was aber selten vorkommt.
Aber die Schüler kündigen doch nicht hier und jetzt auf der Stelle. Sie kündigen zu einem bestimmten Datum. Dieses Kündigungsdatum erfasst du in der Zurdnungstabelle des Teilnehmers zu dem Kurs. - Fertig!
Das musst du doch sowieso machen, oder wie funktioniert das aktuell? Stellen sich die Mitarbeiter einen Wecker auf den Stichtag der Kündigung, und wenn er klingelt löschen sie dann sofort den Teilnehmer aus dem Kurs?

Zitat von: MzKlMu am Januar 28, 2025, 12:47:07Die Historietabellen sind nach meiner Auffassung eine Sackgasse und viel zu umständlich.
Mindestens für die Kursteilnahmen stimme ich hier absolut zu. Bei einem sinnvollen Datenbankdesign ist eine zusätzliche Historientabelle unnötig.
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

Bitsqueezer

Hallo,

also die History-Tabelle ist nicht per se unnütz. Aber ihr eigentlicher Zweck ist in der Tat eher "forensische Datenhaltung", um nachvollziehen zu können, wann welche Änderungen an einem Datensatz gemacht wurde, denn JEDE Änderung am Datensatz wird automatisch einen neuen Eintrag in der History erzeugen. Daraus am Ende eine Statistik zu erstellen mit den Informationen, die dazu notwendig sind, ist dann schon ein wenig Detailarbeit.
Das einzige ist halt, daß die History-Tabelle automatisch von SQL Server verwaltet wird, so daß man sich selbst keine Gedanken um das Konzept machen muß.

Dennoch: Wenn man ganz bestimmte Informationen sichern möchte, sind "herkömmliche" Historientabellen, die man selbst verwaltet, ebenfalls nicht schwer zu realisieren und wahrscheinlich deutlich einfacher auszuwerten. Wenn man eine Tabelle Kurse hat und Personen und dazu eine m:n-Tabelle PersonenZuKursen, dann kann man halt für jede neue Kursbelegung einen neuen Eintrag erzeugen mit Datum, dann hat man ja eine History, die nur Informationen zu Kursen bietet.

Es kommt halt immer darauf an, was man am Ende damit machen will und wieviel Zeit man für die Umsetzung hat. Im Fall der Kursteilnahme ist sicherlich richtig, daß man diese Daten ohnehin erfaßt, sonst würde eine Kursverwaltung ja nicht möglich sein.

Gruß

Christian

MartinHan

wir haben ganz viele Wecker...es klingelt ständig...

nein Spaß´beiseite, eine Änderung einer Kusbelegung ist per sofort möglich. Der Kunde erhält eine Vertragsänderung, die er unterschreibt und die neue Kursbelegung wird eingegeben. Die davor gültig war ist dann weg.
Kündigungen können gelten für den ganzen Vertrag, dann sind auch alle Kursbelegungen gekündigt oder auch nur einzelne Kursbelegungen.
Kursbelegungen können z.B. auch ruhen, wenn jemand längere Zeit krank ist z.B. .
Am Monatsersten werden dann die Beträge für alle Verträge neu berechnet, wo dann eben diese Informationen einfließen und das Geld wird eingezogen. So hat es sich seid 30 Jahren bewährt und ist gängige Praxis in vielen Schulen.

Ihr habe ja alle recht, natürlich könnte ich mit da z.B. mit triggern selbst etwas basteln, aber ich fand die Lösung mit der Historie irgendwie cool...und Zeit habe ich genug, es ist jetzt kein Dringlichkeitsprojekt.
Es gibt nichts gutes, außer, man tut es! EK

Bitsqueezer

Hallo Martin,

also wenn es Dir um Historie geht - warum überschreibst Du denn dann die alten Kursdaten? Es ist doch ebenso leicht, für jede neue Buchung einfach eine neue Zeile einzufügen. Schon ist Dein Problem gelöst.

Gruß

Christian

MzKlMu

Hallo,
ZitatIhr habe ja alle recht, natürlich könnte ich mit da z.B. mit triggern selbst etwas basteln,
Wozu Trigger, egal wo, Datenänderungen sind ein neuer Datensatz. Wozu das noch zusätzlich in Historietabellen schreiben. Und diese Historietabellen sind doch auch nicht gerade einfach. Wenn diese Tabellen sinnvollerweise auch abhängige Daten zeigen sollen, müssen doch diese ebenfalls in weitere Tabellen ausgelagert werden.
Zitatund die neue Kursbelegung wird eingegeben. Die davor gültig war ist dann weg.
Und da genau beginnt doch das Problem. Bevor die neue Kursbelegung eingegeben wird, muss diese doch erst in die Historietabelle geschrieben werden, erst dann kann die Kursbelegung überschrieben werden. Da kann ich die vorherige Kursbelegung doch gleich drin lassen und habe dann meine Historie, automatisch.

Als ich kann diesen Historietabellen nichts abgewinnen. Ich halte diese nach wie vor für Deine Aufgabenstellung für überflüssig. Ändere lieber die DB entsprechend, dass die Daten automatisch auch die Historie abbilden.
Gruß Klaus

MartinHan

#24
Hallo,

ich werde mir alle Ratschläge mal ansehen, ich wollte es aber mit diesen Historischen Tabellen einfach mal machen und möchte dazu erste Eindrücke schildern.
Die DB ist in Produktion soweit stabil, und wenn da noch Fixes zu machen sind, haben ich dafür noch eine separate Umgebung.
Ich habe also für die Tabellen Person, Partner, Kursbelegung, Vertrag, Kurs jeweils Hitorische Tabellen angelegt.
Als Beispiel:
Stefanie besucht die Kurse Ballett 1 und Ballett Fortg., diese Kurs werden mir auch als aktuelle angezeigt.
Es bestehen also 2 Datensätze in der Tabelle Kursbelegung, in denen jeweils die ID der Kurse stehen, der Bezug zu Stefanie geschieht über einen FK, ebenso zu dem Vertrag, zu dem diese Kursbelegungen gehören.
Dann habe ich ihr noch einen weiteren Kurs HopHop 1 zugewiesen.
Das System hat dann in der History Tabelle der Kursbelegung die obigen beiden Kurse abgelegt, also quasi die komplette Belegungskonfiguration...das validTo Datum war dann das Erfassungsdatum des Neuen Kurses. Hätte ich jetzt so nicht erwartet, finde es aber auch gut. Die History Daten der Kurse standen dann auf 2025.1.25 (Der Tag der Einrichtung) bis 9999.12.31.
Dann habe ich ein Änderung an einem der Kurse gemacht und das hatte zur Folge, das der Bezug der Kursbelegung dann auf die historische Tabelle des Kurses zeigte.
Also ich würde mal sagen, das System funtioniert. Natürlich gilt diese Aussage jetzt nur auf diesen kleinen Testfall, wie das Praxix aussieht, wird man sehen.
Ein kleines Problem war dabei aber, das es einige Konstrukte für die Auswertung der temporalen Tabellen in T-SQL gibt, die in Access nicht verfügbar sind:
z.B. FOR SYSTEM_TIME as of @zeitpunkt

D.H. ich hole mir die Daten über eine StP, klappt aber auch problemlos.

Spannend wäre es jetzt natürlich, wenn ich Stephanie komplett lösche, dann dürfte sie in den aktuellen Tabellen gar nicht mehr sichtbar sein, in den historischen aber schon noch.
Es gibt also noch einiges zu testen.

Man lernt nie aus...

Martin
Es gibt nichts gutes, außer, man tut es! EK

MartinHan

Hallo Klaus,

danke für deinen Beitrag.

Bei den einzelnen Datensätzen die Felder Validfrom und Validto einzufügen ist sicherlich denkbar, nur werden die Abfragen dann deutlich komplexer, da ja kaum ein Tabelle alleine da steht, sondern irgendwie verknüpft ist mit anderen und die dann auch wieder einer Historie unterliegen können. Das kann dann sehr komplex werden.
Mit den Temporalen Tabellen habe ich ganz andere Auswertemöglichkeiten, wie hier beschrieben:

https://learn.microsoft.com/de-de/sql/relational-databases/tables/querying-data-in-a-system-versioned-temporal-table?view=sql-server-ver16


Hallo Christian,

danke für deinen Beitrag.
Aber nichts anderes mache ich heute. Wenn eine neue Kursbelegung dazu kommet, erstelle ich einen neuen Satz in der Tabelle Kursbelegung mit einem Erfassungsdatum und schon habe ich die Historie, für neue KB.
Nur bei Löschungen dürfte ich den Satz nicht physisch löschen, sondern müßte ihn z.B. mit einem "gültigbis Datum" kennzeichnen.
Ein update einer KB bezgl. Kurs ist ja nicht weiteres als ein delete mit darauf folgenden insert, so das dann die grade beschriebenen Mechanismen greifen.
Aber nichts anderes machen doch die temporalen Tabellen auch, oder sehe ich das falsch?
Das würde man sicherlich noch hinbekommen...es wird nur diffiziel, wenn noch abhängige Tabellen ins Spiel kommen.
Ich versuche mir Dinge immer bildlich vozustellen. In diesem Szenario sehe die die aktuellen Daten wie auf einem Plateau,ganz oben. Von jeder Tabelle geht eine Treppe nach unten auf der dann die historischen Daten liegen. Kommt eine Version dazu, steigen alle anderen eine Stufe weiter runter und die neue nimmt oben, eine Stufe unter dem Plateau, Platz.
Die Beziehungen zu anderen Tabellen wandern dann auch mit runter, das kann schon recht komplex werden.
Das zu programmieren wäre eine Aufgabe für einen (wie sagen wir im Ruhrgebiet) für einen der Mutter unf Vatter erschlagen hat.
Dazu kommen noch die erweiterten Auswertemöglichkeiten...also für mich haben die temporalen Tallen immer noch die Nase vorn.
Aber ich bleibe weiter dran und hoffe nicht zu langweilen und will mich keineswegs aufdrängen! Wenn ich das tun sollte, bitte ich um Nachricht.

Auch bin ich dankbar für die fachliche Diskussion.

Martin
Es gibt nichts gutes, außer, man tut es! EK

PhilS

Zitat von: MartinHan am Januar 26, 2025, 01:20:56In unseren Verträgen steht:

Mit der Speicherung und Auswertung der Daten nur für den internen Gebrauch bin ich einverstanden.
Mal ganz davon abgesehen, ob das so ausreicht (ich denke eher nicht), was machst du denn, wenn ein Kunde euch explizit zur Löschung seiner Daten auffordert?

Das nur mal als Denkanstoß.
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

Bitsqueezer

Hallo Martin,

in SQL Server gibt es übrigens auch die Option "SET DEFAULT" bei Löschweitergabe. Wenn Du z.B. eine Dummy-Person mit ID 0 anlegst, kannst Du das als Default für eine Personen-ID eintragen. Das kann man auch im Frontend nutzen, um z.B. schon andere Daten zu erfassen, die Person später anzulegen und dann erst in den Kursdaten auswählen.

Vor allem aber kann man das nutzen, wenn jemand verlangt, seine Personendaten zu löschen. SQL Server tauscht dann die PersonenID gegen die 0 aus (oder was immer Du als DummyID benutzen willst), löscht dann aber z.B. die Kursdaten nicht.
Das hat den Vorteil, daß diese von da an anonymisiert sind. Dem Unternehmen gehen die Informationen aber nicht verloren, d.h., man kann z.B. Statistiken über die beliebtesten Kurse oder die, die am meisten einbringen, weiterhin fahren, da solche ohnehin nicht Personendaten mit einschließen. Bei einer normalen Löschweitergabe würden die Daten aber weg sein und dann wird es schwierig.

Der Unterschied der früheren Kurse in der gleichen Tabelle zu History-Tabellen ist ganz einfach, daß die History-Tabellen wirklich JEDE Änderung an einem Datensatz speichern. Nervöse Menschen wie wir Programmierer speichern immer alle paar Sekunden nach einer Änderung ( ;) ), und wenn ein User das auch macht, wird jedesmal ein neuer Datensatz in der History-Tabelle angelegt. Also z.B. einen Namen ändern, dann speichern, dann feststellen, da fehlt noch ein Buchstabe, dann speichern, ach, da ist noch ein Bindestrich zuviel, ändern, speichern... sind schon drei Datensätze in der History-Tabelle. Für Audits ist sowas gut, weil es "forensische" Daten sichert, also wirklich jede Änderung festhält. Für Deinen Zweck ist es sicherlich einfacher, nur einen neuen Kurs anzulegen und den alten entsprechend zu markieren (etwa mit einem Bis-Datum etc.) und dann kann man so oft Änderungen speichern, wie man will. Du hast dann die Kontrolle, welche Änderungen zu neuen Datensätzen führen. Bei History-Tabellen wird jede Änderung an jedem Feld der Tabelle gespeichert. Abhängige Tabellen sind hiermit ebenso ausgeschlossen, da History-Tabellen sich nur auf die Tabelle beschränken, für die sie angelegt wurden.

In dem Kurs-Szenario sehe ich jetzt aber auch nicht sooo viele Abhängigkeiten. Darüber hinaus hättest Du die Möglichkeit, alle zusammenhängenden Daten auch in eine Extratabelle zu schreiben, auch redundant. So wird es etwa in den üblichen Datawarehouse-Datenbanken gemacht, um einfaches und schnelles Reporting zu ermöglichen, da kommt es nicht auf Normalisierung und nicht auf Speicherplatz an. Somit legst Du dann quasi eine Reporting-Datenbank an (kann auch eine getrennte Datenbank sein), ohne zwingend gleich ein professionelles Datawarehouse-Schema zu bauen (was seine ganz eigenen Regeln hat, die ganz anders sind als OLTP-Datenbanken). Also quasi ein Journal, je nachdem, was man sichern möchte, auch mehrere. Damit fallen Abhängigkeiten ganz weg und Du hast ein einfaches Reporting. Quasi die Vorteile aus History-Tabellen und Datawarehouse, aber sehr vereinfacht.
Dabei sind auch nicht zwingend Trigger notwendig (würde ich auch nicht empfehlen, da es zum einen die Speicherung der Daten ein wenig verlangsamt und außerdem muß man sehr vorsichtig bei deren Programmierung sein). Stattdessen z.B. ein Job in einer Reporting-Datenbank, der dort automatisiert z.B. jede Stunde oder wie aktuell es sein soll eine SP auf der Reporting-Datenbank startet, die dann alle aktuellen Daten in die entsprechenden Journaltabellen schreibt.
Berichte, sei es Access, Excel, SSRS, PowerBI oder was immer Du so verwendest, können dann außerdem unabhängig von der eigentlichen Datenbank erstellt werden und belasten diese nicht. Ebenso möglich, die Datenbank auf einen ganz anderen Server zu verlegen, wenn man Performance aufteilen will (aber ich denke, bei einer Ballettschule wohl eher nicht notwendig.. ).

Gruß

Christian

MartinHan

PhilS:

Da sprichst du ein generelles Problem an, was mich schon immer beschäftgt hat.
Ich war 30 Jahre in einem großen IT Unternehmen für Banken beschäftigt.
Dort wurden jeden Tag zig Magnetbänder in einem atomsicheren Bunker verbracht und dort 10 Jahre aufbewahrt (so schreibt es das Gesetz vor).
Wenn jetzt ein Kunde fordert, das alle seine Daten gelöscht werden, so kann er das tun...in den aktuellen Beständen kein Problem.
Es werden aber mit Sicherhet nicht alle Magnetbänder der letzten Jahre durchgesucht, um diesen einen Kunden zu löschen um diese dann neu zu erstellen. Das wird nicht passieren.
Vergleichbar ist es mit unserer kleinen Anwendung.

Natürlich haben wir Sicherungen, als Db-Backup, aber bei aller Geneigheit, ich werde die jetzt nicht wieder einzeln laden, den Kunden entfernen und ein neues Backup ersatellen.

Ich denke, das ist ein Fact, den wir als IT-Leute eingestehen müssen und es wird auch der Öffentlichkeit nicht bewußt sein.

Frage beantworted?

Martin

Es gibt nichts gutes, außer, man tut es! EK

MartinHan

Christian

Danke!
Du schreibst immer so ausführlich, das mus ich erstmal sacken lassen---

Melde mich morgen

Martin
Es gibt nichts gutes, außer, man tut es! EK