Hallo, ich habe eine Frage zu n:m-Beziehungen bei Datenbanken. Laut meinen Recherchen nutzt man diese, sobald Datensätze aus 2 Tabellen gegenseitig mehrfach in Beziehung zueinander stehen können. Ich frage mich nun, ob man n:m-Beziehungen in solchen Fällen grundsätzlich IMMER benutzen sollte, oder ob es durchaus Situationen gibt, in denen man gut darauf verzichten kann? Als Beispiel denke ich an einen Arzt, der zu jedem Patienten die Rezepte inklusive der verschriebenen Medikamente speichert: Auf einem einzelnen Rezept können verschiedene Medikamente aufgelistet sein, gleichzeitig kann ein einzelnes Medikament aber auch auf verschiedenen Rezepten vorkommen. Mit meiner autodidaktischen Datenbank-Erfahrung würde ich vermuten, dass hier eine klassische n:m-Beziehung vorliegt. Aber ist diese auch immer sinnvoll? Mir leuchtet ein, dass man in der Regel wohl ein Rezept eines Patienten aufruft, um nachzusehen, welche Medikamente man diesem verschrieben hat. Die andere Richtung - also ein einzelnes Medikament auszuwählen und dann eine Liste mit Rezepten zu erhalten, auf dem dieses vorkommt - scheint mir im User-Interface einer derartigen Datenbank-Anwendung kein so häufiger Anwendungsfall zu sein. Eventuell für den Fall, dass es eine Rückrufaktion für ein bestimmtes Medikament gibt und man nun alle betroffenen Patienten warnen möchte...wobei ich denke, dass man das auch über eine Select-Anweisung mit entsprechenden Bedingungen erreichen könnte. Gibt es gute Gründe, IMMER eine n:m-Beziehung zu verwenden, wenn die realen Begebenheiten diese Möglichkeit teoretisch vorsehen? Viele Grüße Jan
Jan schrieb: > Als Beispiel denke ich an einen Arzt, der zu jedem Patienten die Rezepte > inklusive der verschriebenen Medikamente speichert: Das Beispiel ist gut gewählt, weil der Zugriff über das Medikament eben weit weniger häufig ist, das kann man wenns doch mal sein soll über einen Suchlauf lösen. Dabei betrachte ich jetzt nicht die "Krankenkassen-Optimierungs-Strategien", die dem Arzt gegen Monatsende raten, mehr von dem einen und weniger von einem anderen Medikament zu verschreiben, das hat ja mit Medizin wenig zu tun. Ist aber wohl trotzdem weit verbreitet. Anderes Beispiel: Rechnung - Kunde. Primär für die Buchhaltung ist die Rechnung (nach Rechnungsnummer), aber über den Kunden auf alle seine Rechnungen zuzugreifen (und zwar sofort) ist ebenso lebenswichtig, etwa bei einer Neubestellung festzustellen, ob er denn seine fälligen Rechnungen auch bezahlt hat. Aber Vorsicht, was akademische Datenbanktheoretiker unbeachtet lassen: eine einmal ausgestellte Rechnung zu verändern ist VERBOTEN, also darf sich die Anschrift auf bereits vorhandenen Rechnungen nicht ändern, wenn im Kundendatensatz eine neue Anschrift eingetragen wird. Die Anschrift zum Datum der Rechnung muss mit dieser abgespeichert werden. Natürlich gibt es auch seriöse Gründe, Rechnungen nachträglich zu ändern, aber bei einer genehmigungsfähigen Buchhaltung darf dies nur durch Stornierung und Ausstellung einer neuen Rechnung geschehen. Egal was die Datenbanktheorie dazu sagt. Georg
Jan schrieb: > Gibt es gute Gründe, IMMER eine n:m-Beziehung zu verwenden, wenn die > realen Begebenheiten diese Möglichkeit teoretisch vorsehen? Ich verstehe dein Problem nicht ganz, das liegt aber vermutlich daran dass ich nicht weiss wie deine Alternative aussähe (am beispiel Patient-medikament)
Guten Morgen Jan, ich sehe es nicht so, dass man immer n:m Beziehungen modellieren sollte. N:M Beziehungen sind nach meiner Auffassung in relationalen Datenbanken immer mit JOIN-Tabellen verbunden, d.h. die hast zwei Tabellen mit "echten" Daten (z.B. Patient und Rezept) und eine Tabelle mit zwei Spalte, welche die beiden Tabellen verknüpft (z.B. Tabelle patient_rezept mit den Spalten patientId und rezeptId). An deinem Beispiel lassen sich gut verschiedenen Beziehungstypen erklären. Ich sehe es so: - Patient -> Rezept: 1:n Beziehung (ein Patient hat im Laufe seinen Lebens mehrere Rezepte. Ein Rezept gehört immer zu einem Patient und kann nicht ohne ihn existieren.) - Rezept -> Medikament: n:m Beziehung (ein Rezept hat mehrere Medikamente und ein Medikament wird in vielen Rezepten gelistet.) - Rezept -> Arzt: n:1 Beziehung (viele Rezepte werden durch einen Arzt ausgestellt) In den Fällen 1:n und n:1 würde ich keine n:m Beziehung in Form ein JOIN Tabelle modellieren. Zusätzliche und fachlich unbegründete JOIN-Tabellen machen deine SQL-Abfragen und den Programmcode komplexer und wenn es sich um mehrere 10-100 Millionen und mehr Datensätzen handelt, auch langsamer. VG, Sascha
Ich verstehe deine Frage nicht so wirklich, da du diese meiner Meinung nach ja schon selbst beantwortest: - Du weißt, dass eine Indextabelle die "Best Practice" ist - Du hast erkannt, dass es in bestimmten Fällen auch anders gehen kann, dies jedoch mit einem "Preis" der deutlich erschwerten Abfragbarkeit in die "andere Richtung" kommt => Wie du somit bereits erkannt hast, kommt es auf den Einzelfall an, zu klären, ob es tatsächlich sinnvoll ist, den (geringen bis sehr geringen) Mehraufwand (Speicher und Ausführungszeit) für die "Best Practice" einzusparen, um im Zweifelsfall viel Aufwand in eine inverse Abfrage zu investieren. Bei Wald-und-Wiesen-Anwendungen wie einer Patientendatenbank beim Arzt würde ich persönlich hier nicht einmal einen Gedanken daran verschwenden und aus Gründen der Wartbarkeit und Übersichtlichkeit die "richtige" Lösung wählen, da hier die Anzahl der SELECTs pro Sekunde eher überschaubar sein sollte, und den eingesparten Entwicklungsaufwand lieber in das richtige Definieren der Schlüssel investieren. Und wenn es um hocheffiziente Anwendungen wie z. B. den Newsfeed auf den Profilseiten bei Facebook, Twitter o. ä. geht, greift man i. A. zu Pufferstrategien, basierend auf Key-Value-Speichern wie memcached, einer zusätzlichen NoSQL-DB etc., und optimiert nicht extrem an der SQL-DB durch besonders trickreiche Abfragen herum.
Ich vergaß: Eine zusätzliche Tabelle schafft natürlich ein zusätzliches Inkonsistenzrisiko; aber da - keine Frage! - jeder DB-Entwickler ausführlich mit Transaktionen arbeitet und alle möglichen Fehlerbedingungen korrekt behandelt und die inkonsistenten Zustände rollbacked, gibt es hier keine Probleme ;-)
Jan schrieb: > Gibt es gute Gründe, IMMER eine n:m-Beziehung zu verwenden, wenn die > realen Begebenheiten diese Möglichkeit teoretisch vorsehen? Die Frage ist, was wäre denn die Alternative? Bei einer n:m-Beziehung in SQL hast Du drei Tabellen: Rezept Rezept_ID Patient_ID Kommentar 123 37 Erkältung 124 99 Grippe 125 42 Hypochonder ... Medikament Medikament_ID Name 3 Paracetamol 4 Schleimlöser 5 Zuckerkugeln ... Rezept_Medikament Rezept_ID Medikament_ID 123 4 124 3 124 4 125 5 ... Wenn Du auf die Zuordnungstabelle "Rezept_Medikament" verzichten willst, bräuchtest Du entweder in Tabelle "Rezept" eine Spalte "Medikament_ID" oder in "Medikament" eine Spalte "Rezept_ID". In die Spalte passt aber zu einem Eintrag nur ein Wert. Also könnte ein Rezept nur ein Medikament enthalten bzw. ein Medikament nur auf einem Rezept verschrieben werden. Das entspricht nicht der Realität. Du müsstest also Umwege finden, z.B. in der Rezept-Tabelle mehrmals das gleiche Rezept mit unterschiedlicher Medikament_ID eintragen. Oder in der Medikament-Tabelle jedes Medikament duplizieren, wenn es einem Rezept zugeordnet wird. Das kann man machen, sollte dafür aber sehr gute Gründe (Performance) haben, denn es macht das Datenbankschema NICHT einfacher, nur weil weniger Tabellen vorhanden sind. Beim Erstellen von anderen Abfragen als dem Hauptanwendungsfall fällt einem das schnell wieder auf die Füße. Man könnte theoretisch auch für die ID-Felder einen anderen Datentyp nehmen, in dem sich mehrere IDs speichern lassen (z.B. als Text oder Blob). Dann kann man allerdings einen Großteil der Vorteile einer Datenbank (SQL, Indizes, Konsistenz, ...) nicht mehr sinnvoll nutzen. Mir fällt kein Anwendungsfall ein, in dem das Vorteile bringen könnte.
Kurze Antwort: jein. Ja: Man ist flexibler, vor allem wenn weitere Anforderungen hinzukommen. Nein: Wenn du weisst dass deine Anforderungen fix bleiben, dann kannst du die ein oder andere Beziehung auch 'hart' abbilden. Hängt auch von den Fähigkeiten deiner DB ab, da kann man dann u.U. auch vieles mit entspr. speziellen Datenstrukturen die DB anbietet erschlagen ohne sich in den Fuss zu schiessen wenn weiter Anforderungen kommen. Ist auch Erfahrungssache wann man auf eine weitere n:m Beziehung verzichtet und das einfach 'hart' abbildet. Faustregel ist: Gewisse Entitäten die evt. noch mit anderen Entitäten in Beziehung stehen könnten (obwohl das erst mal laut Anforderungen gar nicht gefordert ist) bildet man so flexibel wie möglich ab, 'spezielle' Entitäten die auch bei weiteren Anforderungen zu nichts anderem in Beziehung stehen werden bildet man dann eben 'fest' ab, dann bleibt es übersichtlicher.
Ich muss mich auch nochmal zu Worte melden. :-) Ob eine Relationstabelle / JOIN-Tabelle generell zwischen zwei Entitäten immer "Best Practice" und "die richtige Lösung" bezweifle ich. Gerade wenn es starke Bindungen sind, wie bei einer Komposition / Part-of-Beziehung, ist eine Relationstabelle aus meiner Sicht nicht sinnvoll. Die Beziehung Rechnung und Rechnungszeile würde ich als solche einstufen. Man sollte beachten, dass man bei n:m Beziehung nicht so einfach mit cascade delete arbeiten kann, wenn die m-Seite mit gelöscht werden soll (owned). Löscht man ein Element (mit SQL) aus der n-Seite, so kann man mittels cascade-delete zwar die Einträge in der Relationstabelle löschen, aber die Entität auf der m-Seite bleibt bestehen. Hier braucht man dann entweder Code in der Anwendung, der sicherstellt, dass auch die Entitäten der m-Seite gelöscht werden oder Datenbank Triggers. Das macht die Sache unnötig komplex. OK, wenn man OR-Mapping Tools verwendet, braucht man sich darum nicht kümmern. :-) Ich würde auch referenzielle Integrität nicht mit Transaktionen in einen Topf werfen. Zur Sicherstellung, dass bestimmte ID-Spalten nicht ins Nirvana zeigen, gibt es Fremdschlüssel - sofern deine DB-Engine das kann. Transaktionen dienen m.M. nach dazu, die fachliche Korrektheit sicherzustellen (mehrerer DB-Operationen atomar durchführen). Ein Beispiel ist hier eine Überweisung einer Bank bestehend aus den Operationen Abbuchen und Raufbuchen. Just my 2 cents, Sascha
:
Bearbeitet durch User
> Wenn Du auf die Zuordnungstabelle "Rezept_Medikament" verzichten willst
Umgekehrt. Du verzichtest auf die Tabelle "Medikament" und schreibst in
die Tabelle "Rezept_Medikament" den Namen statt die ID.
Da muss man abschätzen, in welche Richtung sich das Programm entwickelt.
Möglicherweise kommt noch eine Spalte Unverträglichkeit dazu. Zunächst
einfach ein unstrukturierter Text. Bei jedem Rezept wird redundant der
aktuelle Warntext abgespeichert. Dann verkaufen die Vertriebler ein
Modul zur Beratung über Unverträglichkeit mit früheren Rezepten...
Hallo zusammen.
Vorab - bevor es Haue gibr - ich kann kein SQL.
> das richtige Definieren der Schlüssel
wie oben beschrieben ist die Sache.
Es muss ja nun mal erst eine Stammdatei geben.
Wenn diese dann die entsprechenden, nötigen Schlüssel enthält,
ist es doch kein Problem, die weiteren Verknüpfungen darzustellen.
Es ist wichtig, sich vorher Gedanken darum zu machen, was diese
Datenbank machen soll. Sie soll doch eine Arbeit vereinfachen,
schneller und besser machen. Dazu gehört, sich den Arbeitsablauf
klar zu machen.
Ich will 1., 2., 3., .....
Das Beispiel mit den Patienten, Rezepten und Medikamenten ist
eigentlich ganz treffend.
Auch den Hinweis, das man manche Dinge hart (sprich Feld) oder
besser weich (Verknüpfung) sollte man beachten.
Es gibt sinnvolle Verknüpfungen und weniger sinnvolle.
Wenn das ganze System aber sinnvoll angelegt ist (richtige Schlüssel),
ist es auch kein Problem, spätere Erweiterungen anzuhängen.
Ich selber habe für eine Apotheke ein Programm für die Verwaltung
der Betäubungsmittel (BTM; Opium ... uiii...) geschrieben. Der Standard
war eine Kartei auf Karteikarten. Ich war die Schreiberei satt.
Für die 'elektronische Kartei' gibt es eine Stammdatei, eine
für die BTMs, eine für den Patienten, eine für den Lieferanten und
eine für den verordnenden Arzt.
In der Stammdatei gibt es Felder für die Verknüpfung zu den anderen
Datenbanken.
Arbeitsgang Eingabe:
Datum, Lieferant, BTM und MengeEin
Arbeitsgang Abgabe:
Datum, BTM, Patient, Arzt, MengeAus
Vom Gesetzgeber gefordert ist ein monatlicher Ausdruck, was
im jeweiligen Monat passiert ist. Also werden beim Drucken die
erforderlichen Verknüpfungen erstellt und das ganze zu
Papier gebracht.
Ich habe es nur verkürzt beschrieben, aber das ist der
Grundarbeitsgang.
JOIN Tabellen habe ich nie gebraucht.
Nicht zu vergessen: zum Schluss aufräumen!
Allen Schutt löschen, den man zwischendurch erzeugt hat!
Ich kann nicht Windooffs. Der ganze Kram funktioniert seit 9 Jahren
unter dBase/Clipper
73
Wilhelm
> Es gibt sinnvolle Verknüpfungen und weniger sinnvolle.
Dummerweise haben da Vertriebler, Verschriftenerfinder, Anwender und
Entwickler vollkommen unterschiedliche Ansichten.
Die für zukünftige Erweiterungen erforderlichen Verknüpfungen kannst du
nur vorhersehen, wenn du keinen Vertrieb hast und selbst mit deinem
Programm arbeitest. Und wenn dich die Vorschriftenerfinder in Ruhe
lassen.
Wilhelm Schürings schrieb: > Vom Gesetzgeber gefordert ist ein monatlicher Ausdruck, was > im jeweiligen Monat passiert ist. Also werden beim Drucken die > erforderlichen Verknüpfungen erstellt und das ganze zu > Papier gebracht. Da fangen dann die parktischen Probleme an, im Gegensatz zur Datenbank-Theorie: wenn seit der Ausgabe an den Stammdaten von Arzt oder Patient was geändert wurde, wird ein Ausdruck erzeugt, der nicht mit dem am Tag der Ausgabe übereinstimmt. Ich fürchte, das ist bei so einem Thema wie Betäubungsmitteln nicht zulässig. Von Fragen nach dem Löschen von Datensätzen usw. mal ganz abgesehen, sonst ermöglicht es das Programm, kiloweise Heroin an der Aufsicht vorbeizuschleusen. Georg
Wo ist das Problem? Du hast eine 1:n Beziehung zwischen Patient und Stammdaten. Die Stammdaten haben als Primärschlüssel Patientenid und Datum. Nach Datenbanktheorie ganz einfach. Ausgabebeleg soll Patientenid und Datum als Fremdschlüssel haben. Probleme entstehen doch eher, weil so etwas meist nicht nach Theorie modelliert wird. Weil da irgendwas mit Stammdaten.Datum <= Ausgabebeleg.Datum zurecht getrickst wird.
Hallo zusammen, Hallo Georg. Das hast du absolut recht. Ich habe in meinem Programm auch keine Routine, in der man die ursprünglichen Daten des Arztes oder Patienten ändern kann. Ich habe solche Zeitgenossen, die in all den Jahren mehrmals umgezogen sind. Also existieren diese Patienten auch entsprechend oft. Auf der anderen Seite relativiert sich die Sache dadurch, dass man den 'Papierkrieg' sprich Ausdrucke nur 3 Jahre aufbewahren muss. Also ist alles älter als 3 Jahre eigentlich nicht mehr wichtig. Auf der anderen Seite: die paar Datensätze zu verwahren, tut auch nicht weh. Jeden Monat ausdrucken und vom Chef zu unterschreiben, so steht es in der Betäubungsmittelverschreibungsverordnung. Ja, so heisst dieses Teil. Für den Amtsapotheker ist auch nur das 'Papier' wichtig. Er wirft einen Blick drauf, und wenn ihm das plausibel erscheint, wird es abgenickt. Man selber hat natürlich den Stress, die Bestände müssen stimmen. Eigentlich sind es immer falsche Eingaben, aber die Fehler muss man dann finden. Diese Art der DB hat natürlich den Nachteil, dass man z.B. nach 3 Jahren die alten Datensätze nicht löschen kann, weil dann ja alle Bezüge verloren gehen. Ich könnte z. B auch noch die Daten von früheren Jahren zu Papier bringen, obwohl sie nicht mehr relevant (Papiere weg) sind. Ich gebe es zu, es sind noch so einige Eseleien im Programm. Eigentlich müsste ich es nochmal neu schreiben. Da ich! meistens damit arbeite, ist es für mich nicht schwierig, Fehler händig mit dBase zu korrigieren. Das ist aber ja eigentlich nicht der Sinn einer professionell genutzten Software. Meine Chefin har grenzloses Vertrauen zu mir -:) Oh, sorry, ich wollte nicht den Thread von Jan kapern... 73 Wihelm
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.