Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Einfaches Datenbankmodell (https://www.delphipraxis.net/196852-einfaches-datenbankmodell.html)

Delbor 25. Jun 2018 15:45

Datenbank: MySQL / Sqlite • Version: 5.5 / 3 • Zugriff über: Firedac

Einfaches Datenbankmodell
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi zusammen

Da ich nicht wirklich Datenbankentwickler bin, sondern solches zur Speicherung meiner Anwendungsdaten einsetze, entwickle ich zur Zeit erst mein 2. DB-Modell:
Anhang 49386
Ziel ist es, Haushaltskosten zu verwalten und die zugehörigen Dokumente als PDF in einer DB vorzuhalten. Und da es sich erst um mein 2. DB-Modell handelt, dachte ich mir, ich frage hier mal nach, ob und welche Fehler ich da eingebaut habe.
  • Zentral ist/sind mal vorerst der oder die User.
  • Der hat eines oder mehrere Einkommen. (Desshalb hier eine 1:n-Beziehung, n auf Seite Salärtabelle)
  • Auch eine Adresse hat er in der Regel nur eine. Wenn mehrere Adressen vorhanden wären, gibt es davon nur eine Erreichbarkeits-Adresse. (Desshalb hier eine 1:1-Beziehung).
  • Gleichzeitig hat er mehrere Verträge mit verschiedenen Firmen, (1:n-Beziehung, n auf Seite Firmen)
  • wovon einer oder mehrere Verträge mit der selben Firma abgeschlossen sein können. (1:n-Beziehung, n auf Seite Verträge)
  • Eine oder mehrere Rechnungen können von ein- und derselben Firma stammen (1:n-Beziehung, n auf Seite Vertrag.) Hier bin ich mir aber nicht ganz im klaren. Zum einen gibt es unbefristete Vertäge (Wohnungsmiete), die periodisch fällig werden (Monatsmiete) und zum andern gibt es Verträge, die jeweils eine Periode gültig sind (zB. ein Jahr) und sich ohne erfolgte Kündigung automatisch teils zu neuen Bedingungen (Krankenkassenprämien) verlängern. Ich denke schon, dass dies eine 1:n-Beziehung ist ( n auf Seite Rechungen)
  • Und zu guter letzt gibt es die Kontotabelle. hier werden alle Bewegungen sämtlicher Konti festgehalten, bzw. zum Teil auch vorausberechnet. Dabei gilt: eine Rechnung wird immer einem einzigen Konto belastet. Trotzdem ergibt sich hier wohl eine 1:n-Beziehung, da mehrere, sich wiederholende Rechnungen (Monatsmiete zB) immer dem selben Konto belastet werden.

Kann dieses Modell stimmen?

Gruss
Delbor

Delphi.Narium 25. Jun 2018 17:51

AW: Einfaches Datenbankmodell
 
Klingt von der Beschreibung her logisch und schlüssig.

Kurze und knappe Beschreibung. Wenn man ein Modell in der Art beschreiben kann, dann passt das meist auch ;-)

Der Anhang lässt sich leider nicht anzeigen, gibt (momentan) 'ne Fehlermeldung. Könntest Du das bitte mal prüfen?

p80286 25. Jun 2018 18:47

AW: Einfaches Datenbankmodell
 
Ich würde eine Vertragstabelle und eine Kündigungstabelle nutzen. Sollte sich aus irgendwelchen Gründen die Kündigungsmodalität ändern könnte man das u.u. nachvollziehen.

Gruß
K-H

Delbor 25. Jun 2018 19:18

AW: Einfaches Datenbankmodell
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hi zusammen

Ich habe den Anhang nun nochmal angehängt, diesmal so wie ich es sonst immer mache, also in der Fusszeile.

Zitat:

Zitat von Delphi.Narium (Beitrag 1405772)
Klingt von der Beschreibung her logisch und schlüssig.
Kurze und knappe Beschreibung. Wenn man ein Modell in der Art beschreiben kann, dann passt das meist auch ;-)
Der Anhang lässt sich leider nicht anzeigen, gibt (momentan) 'ne Fehlermeldung. Könntest Du das bitte mal prüfen?

Anhang 49391

Gleichzeitig hab ichs jeetzt nochmal inn den Text eingebettet, zum Unterschied zu vorhin setzte ich den Cursor jedoch ans Ende der letzten Zeile.
Ein 2. Anhang zeigt das Werkzeug, das ich benutzt habe, nachdem ich das Jpeg hochgeladen hatteAnhang 49392

In der Vorschau sind beide Bilder sichtbarr - das war auch vorhin so.

Gruss
Delbor

jobo 25. Jun 2018 19:34

AW: Einfaches Datenbankmodell
 
Mir ist nicht genau klar, was Du mit "Dokumente" meinst. Die Verträge/Scans?
Ich würde an der Stelle mal einwerfen, dass es neben den Laufzeiten auch folgende "Phänomene" gibt:
- automatische Verlängerung
- Abschlagszahlung (plus Nachzahlung/Erstattung)
- Konditionsänderung
- Beitragsänderung (KFZ, Schadensklasse, Unfall, .. usw)

Ggf. macht es Sinn, die Verträge zu historisieren oder (wechselnde) Optionen anhängen zu können oder die Beiträge separat mit jeweiligem Gültigkeitsdatum (auch voraus) abzulegen.
Ob man, wie in Salär, die Referenzen alle redundant ablegt, ist m.E. Geschmacks- eher aber Performancefrage. Eine Rechnung wird immer eindeutig zu einer Firma und einem Vertrag gehören, das muss in Salär nicht mitgeführt werden.
Es wird dann "schwieriger" innerhalb von Salär zu filtern, aber man spart umgekehrt bei der Befüllung einigen Aufwand. Aus der Rechnungs_id kann man die weiteren Referenzen ermitteln.
Bei Millionen von Einträgen spart man sich bei gewissen Abfragen und Reports mit der reduntanten Variante einige Joins und wird schneller, aber darum geht es hier vermutlich nicht.

hstreicher 25. Jun 2018 19:45

AW: Einfaches Datenbankmodell
 
Hallo

erst mal würde ich auf Umlaute bei Tabellen- und Feldnamen verzichten.

ich würde noch eine Tabelle KontoKopf einführen als 1:N auf Tbl_Konto (Bewegungen)
KontoKopf
ID, Beschreibung ,Adress_ID

Im Tbl_Konto würde ich Bank Varchar durch eine Konto_ID als Foreign Key auf Tabelle KontoKopf ersetzen

Bei Konto würde ich keine Gutschrift/Belastungsfelder führen sondern einfach Betrag Positiv ist eine Gutschrift , negativer Wert eine Belastung ,
macht das aufaddieren einfacher

mfg Hannes

Delphi.Narium 25. Jun 2018 19:58

AW: Einfaches Datenbankmodell
 
Warum gibt es in der TBL_Firma Adresse, Strasse, Nr. und Postleitzahl, wenn die Tabelle doch auch noch 'nen Verweis auf TBL_Adressen hat?

Da scheint mir was redundant zu sein.

Adressen gehören in TBL_Adressen. TBL_Firma bekommt nur 'ne Fremdschlüssel auf TBL_Adressen. Aber die Adressdaten werden dort nicht abgelegt.

Nr. ist vom Typ Int. Was soll das sein? Die Hausnummer? Was wäre dann mit der Hausummer 1a?

Die Tabellen TBL_Firma und TBL_Konto scheinen in dem Bild nicht vollständig enthalten zu sein, könntest Du das noch nachbessern?

Schokohase 25. Jun 2018 20:11

AW: Einfaches Datenbankmodell
 
So eine Firma kann ja auch mal umziehen dann ändert sich eben die Adresse oder wird gekauft und benennt sich um (z.B. von CodeGear nach Embarcadero).

Bei diesem Datenmodell würde so eine Änderungen auch die historischen Rechnungen betreffen, obwohl die Dokumente da etwas anderes sagen werden, denn die sind statisch.

FYI: Grundsätzlich ist es ein sehr schlechter Ansatz eine Anwendung mit dem Datenbank-Modell zu beginnen. Uncle Bob sagt dazu: "The database is a detail and not the center of our application." und weiterhin, dass die Auswahl der konkreten Datenbank erst ganz zum Schluss fällt.

Delphi.Narium 25. Jun 2018 20:23

AW: Einfaches Datenbankmodell
 
Echt jetzt?

Bei Datenbankanwendungen halte ich das Datenmodell für wesentlich. Wenn das stimmt, wird die entsprechende Software geschrieben. Hat die letzten Jahrzehnte immer gut geklappt.

Allerdings sind die meisten Kolleginnen und Kollegen, die es andersherum versucht haben, mehr oder weniger kläglich gescheitert oder haben sowohl Software, als auch Datenmodell permanent anpassen müssen.

Aber vielleicht hab' ich ja auch Pech gehabt und nur die Ausnahmefälle kennen gelernt ;-)

Jedenfalls halte ich es hier konkret für durchaus sinnvoll, sich erstmal Gedanken über die benötigten Daten und die Datenhaltung zu machen und dann die entsprechende Software zu schreiben.

Schokohase 25. Jun 2018 20:46

AW: Einfaches Datenbankmodell
 
Ja.

Hmmm, Datenbankanwendung - daher wird das wohl kommen, denn eine Datenbankanwendung muss eine Datenbank haben, sonst ist es ja nur eine Anwendung.

Oder ist es tatsächlich einfach nur eine Anwendung und egal, wo und wie diese die Daten speichert, solage es passiert?

Noch wahrscheinlicher ist es wohl, dass diese Datenbankanwendung ihren Ursprung in den Datenmodulen und den sich darauf tummelnden RADz-Fatz-Connection-Query-Komponenten. Die laufen tatsächlich nur mit Datenbanken, was es aber nicht besser macht.

Das wird auch der Grund für die Aversion gegen Unit-Tests sein, denn diese sind bei so einem Ansatz gar nicht möglich. (Bitte nicht mit Integration-Tests verwechseln)

Wenn man an dem RAD-Ansatz mit Connection-Query-Komponente auf Form/DateModul festhalten will, dann rüclt man tatsächlich die Datenbank in das Zentrum der Anwendung.

Will man das nicht, dann muss man hier einen gänzlich anderen Weg gehen, sonst passiert genau das, was du beschrieben hast.

Delbor 25. Jun 2018 21:14

AW: Einfaches Datenbankmodell
 
Hi jobo

Zitat:

Ziel ist es, Haushaltskosten zu verwalten und die zugehörigen Dokumente als PDF in einer DB vorzuhalten.
Tatsächlich sind hier im wesentlichen die Verträge und Rechnungen gemeint. Mir fällt aber auf, dass ich bislang eine "Dokumententabelle" vergessen habe für Korrespondenzen aller Art.
Zitat:

Ich würde an der Stelle mal einwerfen, dass es neben den Laufzeiten auch folgende "Phänomene" gibt:
- automatische Verlängerung
- Abschlagszahlung (plus Nachzahlung/Erstattung)
- Konditionsänderung
- Beitragsänderung (KFZ, Schadensklasse, Unfall, .. usw)
Die automatische Verlängerung betrifft zB. die Krankenkasse, wobei jedesmal jährlich eine neue Police mit einem neuen Betrag, aber den ursprünglichen Konditionen(Grundversicherung + diverse allfällige Zusatzversicherungen). Gültig ist hier der ursprüngliche Vertrag, nur eben, dass die fällige Prämie jedes Jahr neu berechnet wird. Das bedeutet: In diesem Fall gibt es jährlich eine neue Police, die aber keine Rechnung ist - die müsste dann in der von mir bislang vergessenen "Dokumententabelle" abgelegt werden.
Dagegen gibt es andere Verträge, die ohne vorliegende rechtzeitige Kündigung auch automatisch verlängert werden, aber ohne dass sich der Betrag ändert.

Grundsätzlich denke ich, sollte es in einem Privathaushalt ausreichen, solche unterschiedlichen Rechnungen nicht in verschiedenen Tabellen zu führen. Ausnahme könnte ein Haushalt sein, der in Wertpapiere diverser Art investiert. Das würde wohl zu einigen zusätzlichen Tabellen führen.

Gruss
Delbor

Delphi.Narium 25. Jun 2018 21:27

AW: Einfaches Datenbankmodell
 
@Schokohase

Das Grundgerüst der Datenhaltung ist die Datenbank.
Die Daten werden dazu ausmodelliert.

Mit was für 'ner Software man dann auf die Daten zugreift ist wurscht.

Man kann auf ein Datenmodell mit 'ner Software zugreifen, die über eine GUI verfügt.
Man kann auch mit Batchprogrammen drauf zugreifen.
Oder ein Webinterface dazu bauen.
Oder ...

Die Daten sind immer in der gleichen Datenbank mit einem Datenmodell.

Das Wesentliche sind die Daten. Die Software ist dazu da, um vereinfacht an die Daten zu kommen.

Delbor will eine Datenbankanwendung schreiben.
Welche Datenbank(en) genutzt wird/werden soll, steht im Eingangspost.

Die Datenbankkomponenten dienen dem Zugriff auf die Datenbank. Sie sind nicht die Ursache für die Nutzung einer Datenbank.

Und wenn man mal mit "richtigen" Daten gearbeitet hat (so ein paar millionen Datensätzen in diversen Tabellen) dann wird man sehr schnell feststellen, dass man zuerst eine vernünftige Analyse benötigt, dann ein Datenmodell dazu und erst dann anfängt die Software zu implementieren.

Und Unit-Tests gehen auch bei Datenbankanwendungen. Damit kann man alle Funktionen des Programmes testen, einschließlich der ggfls. in der Datenbank enthaltenen Logik (Trigger, Datenbankprozeduren ...)

Man muss es halt können ;-)

Der Ansatz ist: Die Software dient zur Bearbeitung der Daten in der Datenbank.

Und nicht:

Die Datenbank ist ein notwendiges Übel, um die vom Programm verabeiteten Daten irgendwie speichern zu können, um sie ggfls. später nochmal zur Verfügung zu haben.

Ich halte Delbors Ansatz, sich erstmal Gedanken über die benötigten Daten und deren sinnvolle Ablage zu machen, für absolut korrekt. Meiner Meinung nach ist das ein professioneller Ansatz.

Schokohase 25. Jun 2018 21:54

AW: Einfaches Datenbankmodell
 
@Delphi.Narium

Wenn du bei einem "Unit-Test" die Trigger der Datenbank mittestest dann hast du per Definition keinen Unit-Test sondern einen Integration-Test.

Das sind zwei paar Schuhe.

Ein Unit-Test testet die kleinst mögliche Einheit (z.B. eine öffentliche Methode) ohne irgendwelche externen Abhängigkeiten (z.B. Datenbanken). Wenn es Abhängigkeiten gibt, dann werden diese per Mock bereitgestellt. So ein Unit-Test ist klein und schnell und wird bei jeder Quelltext-Änderung ausgeführt (siehe TestInsight).

Ein Integration-Test ist wesentlich fetter als der Unit-Test aufgrund der Abhängigkeiten (z.B. von der Datenbank) die jetzt auch mit im Boot sind. Weil diese gewöhnlich (wesentlich) länger dauern als die Unit-Tests, werden diese auch nur zu bestimmten Zeitpunkten ausgeführt (Einchecken im Repository, Release-Build, etc.)

Wer es weiß der kann es auch.

Eine Datenbank ist kein Übel, sondern Mittel zum Zweck und manchmal auch völlig überflüssig und ein paar schlichte Dateien hätten es auch getan.

Natürlich macht man sich Gedanken was für Datenstrukturen die Anwendung benötigt um ihre Aufgabe zu erledigen, aber eben völlig losgelöst von dem eventuell zu verwendenden Datenbank-System.

Hat man diese Strukturen und die Anwendung, dann ist die Datenbank-Anbindung nur noch ein Spaziergang und das Datenbank-System wird austauschbar.

Das ist professionell.

p80286 25. Jun 2018 22:33

AW: Einfaches Datenbankmodell
 
Zunächst, es werden wohl nicht Millionen von Datensätzen werden, daher sind Peformanceüberlegungen eher nebensächlich. Trotzdem spricht nichts gegen ein Datenmodell, das alle Möglichkeiten (oder doch nur 95%,98%..) abdeckt.
@Schokohase
Eine Datenbankanwendung ist die Schnittstelle zwischen Benutzer und den Daten. Nicht mehr und nicht weniger. In dieser Schnittstelle kann man z.B. über Prüfungen sicherstellen, daß nur korrekte Daten in der Datenbank landen. Aber der erste Schritt zu einer solchen Anwendung, ist die Definition der Daten und der Datenhaltung, unabhängig vom später eingesetzten DB-System. Wer hierbei Hausnummern, Postcodes oder Telefonnummern als Zahlen ablegt, legt schon eine fehlerhafte Basis für die spätere Schnittstelle.
Wohin gehört z.B. die Telefonnummer 49211789 ? Ist es 0049211789 oder 049211789 oder doch 49211789 ?
Zitat:

Zitat von Schokohase (Beitrag 1405800)
Eine Datenbank ist kein Übel, sondern Mittel zum Zweck und manchmal auch völlig überflüssig und ein paar schlichte Dateien hätten es auch getan.

Natürlich macht man sich Gedanken was für Datenstrukturen die Anwendung benötigt um ihre Aufgabe zu erledigen, aber eben völlig losgelöst von dem eventuell zu verwendenden Datenbank-System.

Hat man diese Strukturen und die Anwendung, dann ist die Datenbank-Anbindung nur noch ein Spaziergang und das Datenbank-System wird austauschbar.

Ich denke da sind wir jetzt einer Meinung

Gruß
K-H

Schokohase 25. Jun 2018 22:54

AW: Einfaches Datenbankmodell
 
Zitat:

Zitat von p80286 (Beitrag 1405801)
Eine Datenbankanwendung ist die Schnittstelle zwischen Benutzer und den Daten.

Also hat eine Anwendung keine Daten?

Und wenn sie doch Daten hat, aber keine Datenbank, ist es dann eine Datenanwendung oder eher eine DatenOhneBankanwendung?

Bei mir ist jede Anwendung eine Schnittstelle zwischen Benutzer und Daten. Und die Daten liegen irgendwo, der Anwendung grundsätzlich egal, denn die bekommt den Zugriff auf die Daten über eine Abstraktion zugeteilt.

Ist es dann eine IrgendwoDatenanwendung?

Delbor 26. Jun 2018 07:08

AW: Einfaches Datenbankmodell
 
Hi p80286

Zitat:

Zitat von p80286 (Beitrag 1405778)
Ich würde eine Vertragstabelle und eine Kündigungstabelle nutzen. Sollte sich aus irgendwelchen Gründen die Kündigungsmodalität ändern könnte man das u.u. nachvollziehen.

Sowas nachvollziehen zu können, ist sicher wichtig. Ob eine spezielle Kündigungstabelle allerdings Sinn macht, bin ich mir nicht ganz sicher. Ich hab andernorts erwähnt, dass ich vergessen habe, eine Dokumententabelle mit ins Modell einzubeziehen. Andrerseits - eine Dokumententabelle wäre für Dokumente inklusive jeglicher Korrespondenz zuständig. Eine Kündigungstabelle könnte so eine Dokumententabelle entlasten.

Gruss
Delbor

TigerLilly 26. Jun 2018 07:31

AW: Einfaches Datenbankmodell
 
Vielleicht zurück zum Anliegen des TE. Ergänzend zu noch nicht Gesagtem:

Allgemein:
* Die Tabellen alle mit TBL_ beginnen zu lassen ist überflüssig.
* Ich bevorzuge es, die IDs (=PKs) mit dem Tabellennamen zu benennen. So wie du es bei Tbl_User gemacht hast (Tbl_USer -> UserID), aber bei den anderen nicht (Tbl_Konto -> ID)
* Die IDs einmal mit und einmal ohne _ zu bennen ist nicht gut. Adress_ID und UserID ist eine ziemliche Fehlerquelle.
* Ich würde nicht mit den Standarddatentypen arbeiten, sondern UDDT, also selbst definierte Typen, verwenden + allen Feldern, die gleichen Typ haben, diesen zuordnen. Also statt FLOAT bei Beträgen würde ich einen UDDT "Betrag" vom Typ Float zwischenschalten. Diesen ev. mit Default oder not null etc aufpeppen. Das macht es dann zB leichter alle Telefonnummern zu verlängern, weil du nur einmal den UDDT ändern musst.
* Mach dich über den Unterschied zwischen VARCHAR und NVARCHAR schlau.
* INT INTEGER DEC FLOAT ist ein ziemliches Typgemisch - siehe vorher UDDT.
* "Text" als Feldname ist unglücklich, da a) nichtssagend + b) oft ein reserviertes Wort.
* Tabellennamen sollten einheitlich entweder alle Einzahl oder alle Mehrzahl sein. Jetzt gibt es die Tbl_Firma, aber auch die Tbl_Adressen.


Tbl_Konto
* Wenn Saldo die Differenz/Summe aus Gutschrift und Belastung ist, lass es. Das kannst du als Abfrage ausrechnen. Außer du musst Rundungseffekte berücksichtigen, dann kann das sinnvoll sein.
* Vertrag_ID verweist wohin? Ist das nicht redundant, denn über die Rechnung kommst du ja auch zum Vertrag?

Tbl_Adressen
* Mir fehlt da Land+PLZ+eine zweite Adresszeile
* 45 zeichen für die Straße können knapp werden
* Das Design ist da etwas komisch - es gibt Adressen + User+Firmen bekommen welche zugeordnet?

Tbl_User
* da gibt es drei Verweise in die Tbl_Adressen. Warum?

Ich lass es mal gut sein - da gibt es schon Dinge zum Bessermachen :thumb:

Delbor 26. Jun 2018 08:09

AW: Einfaches Datenbankmodell
 
Hi hstreicher
Zitat:

Zitat von hstreicher (Beitrag 1405784)
Hallo
erst mal würde ich auf Umlaute bei Tabellen- und Feldnamen verzichten.

Stimmt. Pascal akzeptiert keine Bezeichner mit Umlauten.

Zitat:

Zitat von hstreicher (Beitrag 1405784)
ich würde noch eine Tabelle KontoKopf einführen als 1:N auf Tbl_Konto (Bewegungen)
KontoKopf
ID, Beschreibung ,Adress_ID

Im Tbl_Konto würde ich Bank Varchar durch eine Konto_ID als Foreign Key auf Tabelle KontoKopf ersetzen

Bei Konto würde ich keine Gutschrift/Belastungsfelder führen sondern einfach Betrag Positiv ist eine Gutschrift , negativer Wert eine Belastung ,
macht das aufaddieren einfacher

mfg Hannes

Das erinnert mich an die Webseite meiner Bank. Da werden neuerdings auch alle Buchungen untereinander aufgeführt. Sowas nennt sich dann 'modernes Webdesign' - ich finde es nur wesentlich unübersichtlicher.
Andere Webseiten wurden auch 'modernisiert' und präsentieren sich nun auf einem Desktop genau so, wie auf einem Mobile - man darf auch genauso oft Scrollen. Nur scrollt eine Mausradumdrehung nicht so weit wie ein Fingerwisch - ich empfinde diesen 'Modernisierungswahn' schlicht und einfach fürchterlich.
Im Code ist das auch nicht gerade Zielführend: du musst (d.h. das SQL) jede Zeile lesen und auf Vorzeichen prüfen. Im Falle einer Anwendung wie die von mir geplante fällt dies wohl weniger ins Gewicht, aber bei bei Millionen von Datensätzen sieht das anders aus.
Ich bin mir nicht sicher, ob eine weitere Normalisierung im Bereich der Kontotabelle Sinn macht, nichtzuletzt eben auch wegen der zu erwartenden Datenmenge.
Andrerseits müssten in der eigentlichen Kontotabelle nur die Datensätze mit dem richtigen Index (Integer) gelesen werden.

Gruss
Dellbor

TigerLilly 26. Jun 2018 08:17

AW: Einfaches Datenbankmodell
 
Zitat:

Ich bin mir nicht sicher, ob eine weitere Normalisierung im Bereich der Kontotabelle Sinn macht, nichtzuletzt eben auch wegen der zu erwartenden Datenmenge.
Neinneinnein. Zuerst wird es richtig gemacht + danach kann man über so was nachdenken + kommt dabei drauf, dass Normalisierung ihren Sinn hat + man nicht darauf verzichten muss/darf/soll.

Delbor 26. Jun 2018 08:45

AW: Einfaches Datenbankmodell
 
Hi Delphi.Narium
Zitat:

Zitat von Delphi.Narium (Beitrag 1405785)
Warum gibt es in der TBL_Firma Adresse, Strasse, Nr. und Postleitzahl, wenn die Tabelle doch auch noch 'nen Verweis auf TBL_Adressen hat?
Da scheint mir was redundant zu sein.

Adressen gehören in TBL_Adressen. TBL_Firma bekommt nur 'ne Fremdschlüssel auf TBL_Adressen. Aber die Adressdaten werden dort nicht abgelegt.

Das ist schlicht ein Flüchtigkeitsfehler - ich hatte die Adresstabelle zusätzlich angehängt, ohne dabei die Firmen-Tabelle nochmal zu überprüfen/annzupassen.

Zitat:

Zitat von Delphi.Narium (Beitrag 1405785)
Nr. ist vom Typ Int. Was soll das sein? Die Hausnummer? Was wäre dann mit der Hausummer 1a?

Die Tabellen TBL_Firma und TBL_Konto scheinen in dem Bild nicht vollständig enthalten zu sein, könntest Du das noch nachbessern?

Die Sache mit der Nr. ist auch ein Flüchtigkeitsfehler, der allerdings schon fast an Dummheit grenzt. Eigentlich solllte es ein Varchar(5) werden.
Voraussichtllich noch heute morgen werde ich das Modell überarbeiten und hier einstellen und dabei auch dies berücksichtigen - offensichtlich habe ich beim Erstellen des Screenshots den unteren Rahmen zu knapp gezogen.

Gruss
Delbor

Delbor 26. Jun 2018 09:07

AW: Einfaches Datenbankmodell
 
Hi zusammen
Zitat:

Zitat von Delphi.Narium (Beitrag 1405799)
Delbor will eine Datenbankanwendung schreiben.
Welche Datenbank(en) genutzt wird/werden soll, steht im Eingangspost.

Um dies etws zu präzidieren: Das DB-Modell wurde/wird mit MySQL Workbench erstellt. Standartmässig können damit auch MySQL-Datenbanken erstellt werden(ForwardIngeneering). Es gibt aber ein Plugin für MySQL-Workbench, das die MySQL-DDL-Statements in solche, die für SQLite optimiert sind, exportiert.. Dieses werde ich allerdings wohl löschen und neu installieren müssen - zum Schluuss wird mir eine Fehlermeldung um die Ohren geschlage, wonach eine oder mehrere Python-Dateien fehlen.

Gruss
Delbor

Delphi.Narium 26. Jun 2018 09:28

AW: Einfaches Datenbankmodell
 
Zitat:

Zitat von Schokohase (Beitrag 1405800)
@Delphi.Narium

Wenn du bei einem "Unit-Test" die Trigger der Datenbank mittestest dann hast du per Definition keinen Unit-Test sondern einen Integration-Test.

Das sind zwei paar Schuhe.

Ein Unit-Test testet die kleinst mögliche Einheit (z.B. eine öffentliche Methode) ohne irgendwelche externen Abhängigkeiten (z.B. Datenbanken). Wenn es Abhängigkeiten gibt, dann werden diese per Mock bereitgestellt. So ein Unit-Test ist klein und schnell und wird bei jeder Quelltext-Änderung ausgeführt (siehe TestInsight).

Ein Integration-Test ist wesentlich fetter als der Unit-Test aufgrund der Abhängigkeiten (z.B. von der Datenbank) die jetzt auch mit im Boot sind. Weil diese gewöhnlich (wesentlich) länger dauern als die Unit-Tests, werden diese auch nur zu bestimmten Zeitpunkten ausgeführt (Einchecken im Repository, Release-Build, etc.)

Wer es weiß der kann es auch.

Eine Datenbank ist kein Übel, sondern Mittel zum Zweck und manchmal auch völlig überflüssig und ein paar schlichte Dateien hätten es auch getan.

Natürlich macht man sich Gedanken was für Datenstrukturen die Anwendung benötigt um ihre Aufgabe zu erledigen, aber eben völlig losgelöst von dem eventuell zu verwendenden Datenbank-System.

Hat man diese Strukturen und die Anwendung, dann ist die Datenbank-Anbindung nur noch ein Spaziergang und das Datenbank-System wird austauschbar.

Das ist professionell.

Meine Datenbankanwendungen sind grundsätzlich so geschrieben, dass ihnen die darunterliegende Datenbank egal ist. Bin es gewohnt mit Datenmengen umzugehen, bei denen sich eine Datenhaltung außerhalb einer Datenbank verbietet. Man müsste dann quasi selbst eine Datenbank implementieren, um mit den Datenmengen umgehen zu können. Das ist unsinnig und zu aufwändig.

D. h.: Die Datenbank ist (annähernd) beliebig austauschbar, aber das Datenmodell ist immer gleich. (Annähernd deshalb: Es gibt zwar 'nen SQL-Standard, aber so wirklich 100% kompatibel sind die Datenbanken da nicht.)
Aber es gibt Möglichkeiten das so flexibel zu gestalten, dass man ohne Programmänderung trotzdem die Datenbank wechseln kann.

Delbor 26. Jun 2018 13:02

AW: Einfaches Datenbankmodell
 
Hi TigerLilly
Danke für deine Antwort! Sehr umfassend!
Zitat:

Zitat von TigerLilly (Beitrag 1405815)
Vielleicht zurück zum Anliegen des TE. Ergänzend zu noch nicht Gesagtem:

Allgemein:
* Die Tabellen alle mit TBL_ beginnen zu lassen ist überflüssig.
* Ich bevorzuge es, die IDs (=PKs) mit dem Tabellennamen zu benennen. So wie du es bei Tbl_User gemacht hast (Tbl_USer -> UserID), aber bei den anderen nicht (Tbl_Konto -> ID)
* Die IDs einmal mit und einmal ohne _ zu bennen ist nicht gut. Adress_ID und UserID ist eine ziemliche Fehlerquelle.
* Ich würde nicht mit den Standarddatentypen arbeiten, sondern UDDT, also selbst definierte Typen, verwenden + allen Feldern, die gleichen Typ haben, diesen zuordnen. Also statt FLOAT bei Beträgen würde ich einen UDDT "Betrag" vom Typ Float zwischenschalten. Diesen ev. mit Default oder not null etc aufpeppen. Das macht es dann zB leichter alle Telefonnummern zu verlängern, weil du nur einmal den UDDT ändern musst.
* Mach dich über den Unterschied zwischen VARCHAR und NVARCHAR schlau.
* INT INTEGER DEC FLOAT ist ein ziemliches Typgemisch - siehe vorher UDDT.
* "Text" als Feldname ist unglücklich, da a) nichtssagend + b) oft ein reserviertes Wort.
* Tabellennamen sollten einheitlich entweder alle Einzahl oder alle Mehrzahl sein. Jetzt gibt es die Tbl_Firma, aber auch die Tbl_Adressen.


Tbl_Konto
* Wenn Saldo die Differenz/Summe aus Gutschrift und Belastung ist, lass es. Das kannst du als Abfrage ausrechnen. Außer du musst Rundungseffekte berücksichtigen, dann kann das sinnvoll sein.
* Vertrag_ID verweist wohin? Ist das nicht redundant, denn über die Rechnung kommst du ja auch zum Vertrag?

Tbl_Adressen
* Mir fehlt da Land+PLZ+eine zweite Adresszeile
* 45 zeichen für die Straße können knapp werden
* Das Design ist da etwas komisch - es gibt Adressen + User+Firmen bekommen welche zugeordnet?

Tbl_User
* da gibt es drei Verweise in die Tbl_Adressen. Warum?

Ich lass es mal gut sein - da gibt es schon Dinge zum Bessermachen :thumb:

Zu Allgemein:
  1. In der Bilddatenbanh hatte ich ursprüngich Namen wie 'Bildtabelle' oder 'KategorienTabelle verwendert. Workbench generierte daraus im Falle von Interselektionstabellen Feldname wie 'Bildtabelle_to_KategorienTabelle' oder 'BildtabelleFeldname_to_KategorienTabelleFeldname' . Irgendwann hab ich das dann geändert und möglichst kurze Namen verwendet, wobei ich das'Tbl_' einführte - das soll mir vor allem im Code klar aufzeigen, dass ich mit einer Tabelle arbeite.
  2. Das ist sicher übersichtlicher
  3. Werd ich korrigieren
  4. ??
  5. Werd ich korrigieren. Wenn ich das richtig verstehe (was ich im Moment eher bezweifle), ergibt das einen Datentyp, der aus mehren Feldern besteht - wobei: Nur einmal den UDDT ändern zu müssen, klingt schomal gut.. Zu UDDT hab ich bisher dies und das gefunden. Noch nicht viel, wie ich finde.

Das überarbeitete Modell steht soweit, ich muss es allerdings nochmal durchsehen.

Gruss
Delbor

TigerLilly 26. Jun 2018 15:00

AW: Einfaches Datenbankmodell
 
Sorry, ich hab nicht gesehen, dass SQLite dein target ist. UDDTs gehen da gar nicht + VARCHAR/NVARCHAR auch nicht.

Delbor 26. Jun 2018 16:39

AW: Einfaches Datenbankmodell
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi zusammen

@ TigerLilly:
Ich werde wohl noch andere Datentypen von Hand anppassen müssen, wenn es mir nicht gelingt, das Workbench-Plugin für SQLite-Export neu zu installieren. Wobei das wohl alles nuur halb so wild ist, wie es sich anhört: ich habe auch noch das Tool SQLIte Expert auf der Platte - leider nur in der Personal-Edition. Die Professional hätte einen grafischen Designer ála Workbench mit an Board. Leider sehe ich keine Möglichkeit, das Ding Online zu kaufen - preislich würde es sich durchaus in einem vertretbaren Rahmen halten.
Anrerseits liessen sich die Tabellen auch mit der Personal aufgrund des Workbench-Modells erstellen - zwar mehr oder weniger 'von Hand. Egal, irgendwie krieg ich das schon hin.

Inzwischen habe ich das Modell überarbeitet:
Anhang 49400

Ich hab auch eine Kontobeschreibungs-Tabelle eingebaut, analog zur Empfehlung von hstreicher, eine Kontokopf-Tabelle einzuführen - ich seh mich schon, wie ich mir an den Kopf greife angesichts einer Bildschirmseite voller gleichlautender Kontonamen...
Beim ersten Entwurf der Tabellen hatte ich die erfordrlichen Fremdschlüssel-Felder mit eingefügt, und als ich die Beziehungen einzeichnete, tat Workbench nochmals dasselbe - ich hoffe nur, ich hab jetzt alle "Bösewichte" erwischt.

Gruss
Delbor

mkinzler 26. Jun 2018 17:13

AW: Einfaches Datenbankmodell
 
Liste der Anhänge anzeigen (Anzahl: 1)
Alternativ die Community Edition von DBeaver

https://dbeaver.io/

Delphi.Narium 26. Jun 2018 17:15

AW: Einfaches Datenbankmodell
 
Schau Dir bitte nochmal die ganzen Fremdschlüssel an, da scheint einiges mehrfach zu sein.

Warum hat TblAdressen einen Fremdschlüssel auf Tbl_User_UserID? Müsste das nicht umgekehrt sein? Ein User verweist auf eine der Adressen und nicht eine Adresse verweist auf einen User?
Was ist denn, wenn zwei User die gleiche Adresse haben? Wird die Adresse dann doppelt abgelegt, weil sie nur auf einen User verweisen kann?
Oder müssten nicht die beiden User auf die gleiche Adresse verweisen, um eine doppelte Speicherung einer Adresse zu vermeiden?

Warum ist die Kontonr vom Typ Int? Gibt es keine Kontonummern mit führenden Nullen?
Warum ist die KontoNr auch als Konto-Nr in der Tbl_Kontobeschreibung enthalten? Sind damit unterschiedliche Kontonummern gemeint?

Warum heißt die Tabelle TblUser TblUser, aber die Fremdschlüssel, die auf sie verweisen, Tbl_User_UserID.

Warum gibt es in der Tabelle TblRechnungen einen Fremdschlüssel Tbl_Vertrag_Tbl_Firma_ID.
'ne Rechnung gehört zu einem Vertrag, ein Vertrag zu einer Firma, aber deshalb muss die Rechnung noch lange keinen Fremdschlüssel auf den Vertrag haben. Das ist eine zusätzlich zu pflegende Redundanz (die man allenfalls bei 'ner (z. B. aus Performanzgründen erforderlichen) Denormalisierung einführen kann.

Ähnliches kommt wiederholt vor.

Delbor 27. Jun 2018 09:27

AW: Einfaches Datenbankmodell
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi Delphi.Narium

Zitat:

Warum hat TblAdressen einen Fremdschlüssel auf Tbl_User_UserID?
Ich habe da eine 1.1-Beziehung eingerichtet, da ich davon ausgegangen bin, dass es genau einen User an genau einer Adresse gibt. Aber das ist falsch, da ja auch die Ehefrau des Users Einkommen haben kann und/oder Rechnungen bezahlen muss. Und das Taschengeld der Kinder, bezw. was die damit machen, will/soll auch verwaltet werden/werden können.
Und natürlich können zwei User an der selben Adresse zuhause sein, aber verschiedenen Familien angehören.

Zitat:

Warum ist die Kontonr vom Typ Int? Gibt es keine Kontonummern mit führenden Nullen?
Dass ist schlicht ein Flüchtigkeitsfehler. Ohne wirklich zu wissen, dass es so ist, könnten Kontonummmern wohl auch Alphanummerische Zeichen enthalten.
Zitat:

Warum ist die KontoNr auch als Konto-Nr in der Tbl_Kontobeschreibung enthalten? Sind damit unterschiedliche Kontonummern gemeint?
Auch das ist ein Flüchtigkeitsfehler: ich habe schlicht vergessen, die Kontonummer aus der Kontotabelle zu löschen.

Zitat:

Warum heißt die Tabelle TblUser TblUser, aber die Fremdschlüssel, die auf sie verweisen, Tbl_User_UserID.
Die Fremdschlüssel werden jeweils von Workbench angelegt, aber, wenn ich das richtig gesehen habe, nicht unbedingt angepasst, wenn ich die Beziehung löschen und sie neu anlege.

Zitat:

Warum gibt es in der Tabelle TblRechnungen einen Fremdschlüssel Tbl_Vertrag_Tbl_Firma_ID.
Wie ich oben schon gesagt habe, legt Workbench die Fremdschlüssel an. Und das hat damit zu tun:

Anhang 49404

Wenn hier Restrict festgelegt wird, kann gar nichts gelöscht werden. Bei allen anderen Möglichkeiten müsste ich mich erst schlau machen.

Und nun möchte ich mich endlich ganz herzlich bei mkinzler bedanken. Ab nun werde ich das Modell mit dbeaver neu erstellen.

Gruss
Delbor

TigerLilly 28. Jun 2018 06:49

AW: Einfaches Datenbankmodell
 
Das ist gut zu lesen:
https://www.talend.com/blog/2017/05/...ctices-part-1/

Auch gut ist das Stichwort "Konzeptionelles Datenmodell".
Es gibt viele Tools, die das unterstützen + damit klebt man nicht von beginn an schon an den Möglichkeiten der target-DB.

Rollo62 28. Jun 2018 07:35

AW: Einfaches Datenbankmodell
 
Zitat:

Zitat von TigerLilly (Beitrag 1405815)
Allgemein:
* Die Tabellen alle mit TBL_ beginnen zu lassen ist überflüssig.
* Ich bevorzuge es, die IDs (=PKs) mit dem Tabellennamen zu benennen. So wie du es bei Tbl_User gemacht hast (Tbl_USer -> UserID), aber bei den anderen nicht (Tbl_Konto -> ID)
* Die IDs einmal mit und einmal ohne _ zu bennen ist nicht gut. Adress_ID und UserID ist eine ziemliche Fehlerquelle.
* Ich würde nicht mit den Standarddatentypen arbeiten, sondern UDDT, also selbst definierte Typen, verwenden + allen Feldern, die gleichen Typ haben, diesen zuordnen. Also statt FLOAT bei Beträgen würde ich einen UDDT "Betrag" vom Typ Float zwischenschalten. Diesen ev. mit Default oder not null etc aufpeppen. Das macht es dann zB leichter alle Telefonnummern zu verlängern, weil du nur einmal den UDDT ändern musst.
* Mach dich über den Unterschied zwischen VARCHAR und NVARCHAR schlau.
* INT INTEGER DEC FLOAT ist ein ziemliches Typgemisch - siehe vorher UDDT.
* "Text" als Feldname ist unglücklich, da a) nichtssagend + b) oft ein reserviertes Wort.
* Tabellennamen sollten einheitlich entweder alle Einzahl oder alle Mehrzahl sein. Jetzt gibt es die Tbl_Firma, aber auch die Tbl_Adressen.

Solche Konventionen finde ich immer sehr gut, ich arbeite zwar nicht mit den komplexesten DBs aber hilfreich ist das immer.
Das kann ich Alles unterstreichen, und weiche davon nur in Sonderfällen ab (OK bei den Datentypen manchmal).

Zitat:

* Ich bevorzuge es, die IDs (=PKs) mit dem Tabellennamen zu benennen.
Ich benutze im Moment zwar möglichst konsequent ID, das sit aber eine gute Idee, werde ich mir mal ansehen.

Was ich als Konvention für mich festgestellt habe ist das bei den meisten Tabellen eine
möglichst gleiche Nomenklatur benutzen sein kann (nicht bei Allen Tabellen wohlgemerkt).
In der Art:
  • ID(_xxxx) - als PK
  • Name - Passt fasst immer, da muss ich nicht XxxxName schreiben, denn der Zusammenhang macht es klar
  • Descr - eine Beschreibung zum Eintrag kann ich auch ziemlich oft dazunehmen
  • ChgFirst - Oft ist es sinnvoll den Ersteller des Records zu protokollieren
  • ChgLast - sowie Wer hat den Record zuletzt geändert
  • ChgTime - und wann war das

Rollo

DeddyH 28. Jun 2018 07:41

AW: Einfaches Datenbankmodell
 
Bei mir heißt der PK immer ID, FKs sind nach dem Muster <RefTable>ID benannt, also z.B.
Code:
 CREATE TABLE Address(
  ID INTEGER NOT NULL PRIMARY KEY,
  PersonID INTEGER,
  CONSTRAINT FK_Person
  FOREIGN KEY(PersonID) REFERENCES Person(ID)
)
Letztendlich ist es aber auch wurscht, wie man das handhabt, wichtiger ist in meinen Augen, dass man das Muster erkennen kann und dieses auch konsequent eingehalten wird.

TigerLilly 28. Jun 2018 07:50

AW: Einfaches Datenbankmodell
 
Zitat:

Name - Passt fasst immer, da muss ich nicht XxxxName schreiben, denn der Zusammenhang macht es klar
Ah - guter Punkt. Es sollte (bis auf wenige Ausnahmen) keine gleichbenannten Felder geben. Wenn du einen Join über mehrere Tabellen hast + da kommt 4x "Stadt" vor, hilft dir der Zusammenhang nicht viel.

Zitat:

[*]ChgFirst - Oft ist es sinnvoll den Ersteller des Records zu protokollieren[*]ChgLast - sowie Wer hat den Record zuletzt geändert[*]ChgTime - und wann war das
Ein konzeptionelles Datenmodell versteht "Vererbung" + da kann man sowas gut abbilden.

Ich habe in meinen Tabellen auch noch ein Feld "Serial", das bei Änderungen hochgezählt wird. Dann kann die WHERE Clausel für das Update "where PK=... and Serial=..." lauten + darauf kann man einen knackigen Index setzen.

Zitat:

Bei mir heißt der PK immer ID, FKs sind nach dem Muster <RefTable>ID benannt, also z.B.
Warum nicht gleich <table>ID? Siehe oben - ein Join über 4 Tabellen + du hast 4x ID.
Außerdem: Gleiche Bezeichnung == gleicher Inhalt. (Bis auf wenige Ausnahmen, meistens so Verwaltungsfelder.)

DeddyH 28. Jun 2018 07:54

AW: Einfaches Datenbankmodell
 
Weil <Table>ID bei mir ein Zeichen für einen Fremdschlüssel ist, dann kommt man nicht durcheinander.

mkinzler 28. Jun 2018 07:55

AW: Einfaches Datenbankmodell
 
Zitat:

Warum nicht gleich <table>ID? Siehe oben - ein Join über 4 Tabellen + du hast 4x ID.
Ich nenne PK auch immer nur ID. In Deinem Beispiel könnte man bei der Abfrage Aliase setzen oder die FK-Felder der Detailtabellen.

Rollo62 28. Jun 2018 08:05

AW: Einfaches Datenbankmodell
 
[QUOTE=TigerLilly;1406004]
Zitat:

Wenn du einen Join über mehrere Tabellen hast + da kommt 4x "Stadt" vor, hilft dir der Zusammenhang nicht viel.
Ja ich gebe zu das ich nicht mit superkomplexen DB-Strukturen arbeite (bis auf ein DATEV-Projekt), aber manches lässt sich auch dann besser lesbar darstellen:

Code:
select mi.Personalnummer as MitNr,
       mi.Name as MitName, // Alias
       mi.Vorname,
       dw.ID, dw.Kennzeichen, dw.Fahrzeugtyp_ID as Typ
  from Mitarbeiter mi
       join Dienstwagen dw
         on mi.ID = dw.Mitarbeiter_ID
 where dw.Fahrzeugtyp_ID in ( SELECT ft.ID
                                from Fahrzeugtyp ft
                                     join Fahrzeughersteller Fzg // Alias
                                       on ft.Hersteller_ID = fh.ID
                               where Fzg.Name = 'Mercedes-Benz'); // Alias.Name
Ist jetzt vielleicht nicht das beste Beispiel :stupid:

TigerLilly 28. Jun 2018 09:41

AW: Einfaches Datenbankmodell
 
:thumb: Geschmäcker und so. :-D

Rollo62 28. Jun 2018 10:24

AW: Einfaches Datenbankmodell
 
Nein nein, du hast ja Recht.
Bei 5+ Tabellen im JOIN wird es wohl unübersichtlicher.
Dann bin ich ganz bei dir :thumb:

Ich wollte ja nur mögliche Auswege zeigen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:27 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz