[Datenbankdesign] m:n-Beziehung und die Probleme ;)

PlaciD

Böhser Onkel
ID: 55555
L
11 Februar 2007
722
105
Hallo,

folgendes Problem:

Tabelle User:
userid | username

Tabelle Project:
projectid | projectname

Zwischen den Tabellen user und Project besteht eine m:n-Beziehung, deshalb eine Zuordnungstabelle:

Tabelle UserToProject:
userid | projectid

Soweit alles ganz normal. Nun kommt der Clou: Es soll nun bei jedem Projekt der User gespeichert werden, der Projektmanager ist.
Wenn ich der Tabelle Project eine neue Spalte "projectmanager" gebe, habe ich das Problem, dass ich nicht weiß, ob diese user überhaupt am Projekt teilnimmt (es also in der Zuordnungstabelle einen Eintrag gibt).
Wenn ich es in der Zuordnungstabelle mittels true/false speichere, kann es mehrer Projectmanager geben.
Beides soll natürlich nicht möglich sein.

Wie löse ich dieses Problem?

PlaciD
 
Ich würde hergehen und festlegen, dass der Projektleiter automatisch am Projekt teilnimmt. D.h. die UserID des Leiters in der Projekt-Tabelle speichern, aber keinen Eintrag in UserToProject machen.

Bin gespannt, obs bessere Lösungen gibt.
 
naja ich würde sagen du mußt natürlich immer prüfen ob der Projektleiter bereits user ist (per Script)

mir würde jetzt so auf anhieb nicht einfallen, wie das nur per db machbar wäre.

Aber eben überprüfen sollte doch kein Problem sein!?

*edit*

hmm frage ist natürlich, ob der Projektmaneger auch aktiv am projekt telnehmen kann, oder nur es Leitet (was normal der fall ist), aber was schon normal!?
 
Aber eben überprüfen sollte doch kein Problem sein!?

Wenn nur ein Programm an der Datenbank hängt, dass noch dazu von mir geschrieben wird, ist das sicherlich kein Problem. ABER: Eine gut ausgearbeitete Datenbank kann durch Programme nur noch bedingt mit Fehlinformationen gefüllt werden (jedenfalls logischen). Ich möchte ja die Datenbank designen, nicht alle Programme, die dann später mal in diese Datenbank schreiben, auf Richtigkeit überprüfen. Zumal es immer mal eine externe Schnittstelle/ein von externen geschriebenes Programm geben kann, dass die db genauso nutzt. Und wenn dort von irgendwo Quatsch reingeschrieben wird, ist das Geschrei/sind die Fehler groß ;)

Deshalb fällt die Möglichkeit der Programmüberprüfung aus.

Eine Möglichkeit wäre natürlich ein Trigger. Die Frage ist, ob ich den durch ein besseres Design nicht umgehen kann. Ich bin immer der Meinung, durch eine geschickte Datenstruktur kann man eine db in der 3ten Normalform ohne logische Unstimmigkeiten hinbekommen. Aber in diesem Fall fällt mir irgendwie garnichts ein.

@theHacker: Das wäre glaube ich eine sehr fehleranfällige und "komische" Struktur. Schließlich lese ich ja später die Teilnahmen am Projekt über die Zuordnungstabelle aus und möchte nicht noch extra in die Projekttabelle joinen, nur um den Chef rauszufinden.Das kommt mir intuitiv nicht richtig vor.

Danke für eure Antworten,

PlaciD
 
@theHacker: Das wäre glaube ich eine sehr fehleranfällige und "komische" Struktur. Schließlich lese ich ja später die Teilnahmen am Projekt über die Zuordnungstabelle aus und möchte nicht noch extra in die Projekttabelle joinen, nur um den Chef rauszufinden.Das kommt mir intuitiv nicht richtig vor.
So komisch isses aber vielleicht doch ned :think:

Mein Gedanke geht in etwa in diese Richtung; siehe Bububoomt's Edit:
hmm frage ist natürlich, ob der Projektmaneger auch aktiv am projekt telnehmen kann, oder nur es Leitet (was normal der fall ist), aber was schon normal!?
Der Leiter - wovon es genau einen gibt - ist strenggenommen kein Projektteilnehmer.

Fehleranfällig, ja, wenn man den Projektleiter tauscht, ihn zum Projektmitarbeiter macht und vergisst, ihn in die Tabelle einzutragen.
Legt man aber die Festlegung "Leiter != Mitarbeiter" zu Grunde, ist das ganze System eigentlich in sich stimmig.
 
Fehleranfällig, ja, wenn man den Projektleiter tauscht, ihn zum Projektmitarbeiter macht und vergisst ihn in die Tabelle einzutragen.
Legt man aber die Festlegung "Leiter != Mitarbeiter" zu Grunde, ist das ganze System eigentlich in sich stimmig.

Ok, wenn man das annimmt, schon. An diese Art der Interpretation hatte ich garnicht gedacht. In der Realität ist es aber so, dass es einfach X Teilnehmer gibt, von denen einer dann die Aufgabe des Projektleiters bekommt (der aber genauso Teilnehmer ist). Ich habe mir eben überlegt, dass die Zuordnungstabelle einfach einen boolean bekommt, wer Projektleiter ist. Sollte ein Programm mehr als einen Projektleiter eintragen, dann ist das eben so. Es verletzt keine der Normalformen und auch logisch bleibt eigentlich alles korrekt (es kann ja theoretisch mehrere Projektleiter geben).

Aber falls jemand noch einen ganz anderen Ansatz hat, immer her damit!

PlaciD
 
Wie wäre es, wenn du einfach in UserToProject noch eine set-Spalte hinzufügst, die den "Zustand" des Users angibt (z.B. Teilnehmer, Leiter, Leiter + Teilnehmer)?

Keine Ahnung, ob das uni-konform ist :mrgreen:

Gruß

edit: ja, ich meine ein SET ;)
 
Zuletzt bearbeitet:
Also normalerweise ist der Projektleiter kein Mitarbeiter.
(In Systemanalyse wurde dem Projektleiter strikt verboten etwas zu tun außer die Koordinierung und Zusammentargen der Dokumentation.)

Projektleiter sollte es auch nur einen geben, höchstens gibt es noch Gruppenleiter oder nicht!?

Was für eine DB nutzt du überhaupt? Bei SQL konnte man doch auch Bedingungen angeben. Kann man da nicht angeben, dass der projektleiter in Project auch in UsertoProject vorhanden sein muß?

*edit*
sql->check

CREATE TABLE ERGEBNIS (
STID SMALLINT NOT NULL,
LKID INTEGER NOT NULL,
AUID CHAR(6) NOT NULL,
PUNKTE SMALLINT,
CHECK (punkte >= 0 AND
punkte <=
(SELECT maxpunkte FROM aufgabe au
WHERE ergebnis.auid = au.auid AND ergebnis.lkid=au.lkid))),
FOREIGN KEY (STID,LKID) REFERENCES TEILNAHME(STID,LKID)
ON UPDATE CASCADE
);
 
Was für eine DB nutzt du überhaupt? Bei SQL konnte man doch auch Bedingungen angeben. Kann man da nicht angeben, dass der projektleiter in Project auch in UsertoProject vorhanden sein muß?

*edit*
sql->check

Das scheint die Lösung zu sein; ich danke dir sehr! Das sieht doch schonmal sehr gut aus. Ich nutze mySQL und werde es gleich mal ausprobieren.

Zu "Projektleiter != Mitarbeiter": Das mag fachlich so sein, aber das ganze technisch umzusetzen, vor allem in kleinere Projekten, ist faktisch unmöglich. Geh mal in eine 10-Mann-Firma, die werden dir den Vogel zeigen, wenn du denen sagst, dass der Projektleiter nix machen darf.

@Johnson: Das ändert noch nichts am Problem, dass es dann mehrere Projektleiter geben kann.

Ich probiere die Idee von Bububoomt mal aus und melde mich dann nochmal.

EDIT:
The CHECK clause is parsed but ignored by all storage engines.

:(

PlaciD
 
Zuletzt bearbeitet:
sorry dich zu entäuschen, aber meines wissens nach gibts das bei mySQL nicht, da hast du ja auch andere Sachen nicht wie bei SQL.

Delete on Cascade etc. gibts ja auch net, oder gibts das in den neusten Versionen inzwischen!?

*edit*
ok Foreign Keys mit InnoDB gibts das, habe ich nicht genutzt bisher...
 
Delete on Cascade etc. gibts ja auch net, oder gibts das in den neusten Versionen inzwischen!?

*edit*
ok Foreign Keys mit InnoDB gibts das, habe ich nicht genutzt bisher...

Also DELETE ON CASCADE gibt es bei mySQl genauso wie Foreign Keys (die glaube ich schon seit längerem).

Ich habs jetzt gerade mittels eines Foreign Keys gelöst, ist ja eigentlich eine total einfache Lösung. Weil wenn ich den projectmanager als foreign key auf die spalte userid in der Zuordnungstabelle lege, passiert genau das was ich will. Wenn jemand den Projekt-Manager einträgt, ohne das dieser Teil des Projekts ist, gibts ne Fehlermeldung :)

PlaciD
 
Sollte ein Programm mehr als einen Projektleiter eintragen, dann ist das eben so. Es verletzt keine der Normalformen und auch logisch bleibt eigentlich alles korrekt (es kann ja theoretisch mehrere Projektleiter geben).

Aber falls jemand noch einen ganz anderen Ansatz hat, immer her damit!
für solche Probleme gibt es Prepared Statements, der Programmierer hat keinen Zugriff mehr direkt auf die Tabellen sondern erwirkt Veränderungen durch Prepared Statements, die du codest und somit die Regeln festlegst


So wie ich das gesehen habe gibts das aber ja nur in der InnodB nicht in der MyISAM
richtig :yes:
 
für solche Probleme gibt es Prepared Statements, der Programmierer hat keinen Zugriff mehr direkt auf die Tabellen sondern erwirkt Veränderungen durch Prepared Statements, die du codest und somit die Regeln festlegst

ähm nein... :ugly:

Und zum Thema... ich würde in der Auflösungstabelle der n:m Beziehung einfach ein extra Feld für rollen machen. Somit kann man auch andere Aufgabenbereiche festhalten.