Hallo zusammen, ich habe in einer Datenbank (postgresql) 2 Tabellen in der Form: Tabelle 1: ID(serial), key(int FK) Tabelle 2: key(int PK), data(int) Zwischen diesen Tabellen möchte ich eine n:1-Beziehung, wobei n nicht gleich 0 sein darf. Mit anderen Worten: In Tabelle 2 darf keine Zeile existieren, deren key nicht in Tabelle 1 ist. Und da stehe ich irgendwie auf dem Schlauch. Ein Lösungsansatz von mir, dies nicht auf Datenbankebene sondern auf Applikationsebene zu lösen, in dem ich programmgesteuert alle Einträge überprüfe. Dies würde funktionieren, ist aber in meinen Augen nicht sauber gelöst. Auf der anderen Seite, selbst wenn ich diese Abhängigkeit hinkriege hätte ich keine Ahnung, wie ich neue Datensätze anlegen kann, da beide Tabellen voneinander abhängig sind, müssten die beiden Datensätze gleichzeitig angelegt werden (aber wahrscheinlich mit SQL irgendwie machbar). Jemand eine Idee? Gerd der Hintergrund: In der Datenbank ist unter anderem ein Abbild eines Verzeichnisses gesichert. In Tabelle A liegen die Dateinamen, in Tabelle B die iNodes. Da durch Links, mehrere Dateien die selbe Inode haben können aber eine Inode zwingend mindestens einen Dateinamen braucht ergibt sich das Problem.
Henne-Ei Problem? Um in Tab1 was eintragen zu können muss der Key schon in Tab2 drin sein. Das genau willst du aber verbieten.
Kannst versuchen, umgekehrt vorzugehen. Also z.B. an Löschaktionen in Tab1 einen Trigger dranhängen, der ggf. den Eintrag in Tab2 löscht.
Es gibt in PostgreSQL die Möglichkeit innerhalb einer Transaktion die Constraint-Überprüfungen zu deaktivieren: http://www.postgresql.org/docs/9.1/static/sql-set-constraints.html Ich persönlich würde zwar versuchen es anders zu lösen, vielleicht ist es aber für dich nützlich.
Oliver R. schrieb: > Es gibt in PostgreSQL die Möglichkeit innerhalb einer Transaktion die > Constraint-Überprüfungen zu deaktivieren: Aufgeschoben, aka DEFERRED, würde besser passen.
Vielleicht sowas: The FOREIGN KEY constraint is used to prevent actions that would destroy links between tables. The FOREIGN KEY constraint also prevents invalid data from being inserted into the foreign key column, because it has to be one of the values contained in the table it points to. http://www.w3schools.com/sql/sql_foreignkey.asp Und noch die Super Erklärung.. Options wäre interessant in diesem Link: https://de.wikibooks.org/wiki/Einf%C3%BChrung_in_SQL:_Fremdschl%C3%BCssel-Beziehungen
:
Bearbeitet durch User
Hm, vielen Dank soweit. Ich beginne zu glauben, dass mein Vorhaben nicht umsetzbar ist. Der Ansatz das ganze über eine Transaction zu erledigen in der ich die CONSTRAINTS auf DEFERED setze um die Überprüfung erst am Ende der Transaktion durchzuführen klingt gut. Allerdings scheitere ich schon einen Schritt vorher. Ich habe nun versucht die beiden Tabellen zu erstellen, was nicht möglich ist. psql lässt die Erstellung von TabB nicht zu. Begründung: Der Wert von Key in TabA ist nicht eindeutig. Diese Eindeutigkeit kann es jedoch nicht geben, denn es sollen ja eben mehrere Einträge in TabA auf B verweisen. Allerdings steht dies im Gegensatz zur Funktionsweise von Fremdschlüsseln. Das ganze führt dazu, dass ich den gesammten Entwurf wohl ändern muss. Aktuell sehe ich nur eine andere Möglichkeit: Einfügen einer weiteren Tabelle zur Verknüpfung. Eigenetlich für m:n Beziehungen TabA 1: ID(int PK) name(text) TabB 2: ID(int PK) inode(int) TabC 3: id_a(int FK UNIQUE), id_b(int FK) Dazu müsste ich jetzt der Datenbank sagen, dass es für jeden Eintrag in A mindest einen Eintrag in C geben muss. k.A. ob, dies möglich (und sinnvoll) ist. Zwar finde ich noch andere Möglichkeiten, jedoch verstossen diese gegen die Normalisierung. Darüber könnte man hinwegsehen, aber dann habe ich keine Vorteile mehr gegenüber meiner ursprünglichen Lösung. Die Konsistenz müsste ich dann immer wieder händisch prüfen. tldr: Das Einfügen ist aktuell nicht mehr mein Problem. Ich müsste erst einmal die dafür notwendigen Tabellen erstellen, und da scheitere ich schon. Jemand noch eine Idee für ein vernünftiges Design? Gerd
Philipp K. schrieb: > http://sqlfiddle.com/#!15/274f0/15 Danke. Eine Lösung scheint es leider nicht für mich zu sein. Dort beschrieben ist eine 1:n Beziehung. In der Tabelle cities kann eine Stadt existieren, ohne dass in der Tabelle weather eine zugehöriger Datensatz existiert. Dies ist genau der Umstand den ich vermeiden möchte. So wie ich es sehe, würde ein Löschen eines Datensatzes in cities auch die zugehörigen Datensätze in weather löschen. Nur andersrum halt nicht.
Dann definiere doch ein DefaultWeather in cities. Darauf noch ein constraint und das DefaultWeather mandatory. Dann hättest du doch deinen Wunsch oder nicht?
Ja moment mal aber Du bist doch der Auslöser einer City.. wenn Du nie eine City schreibst dann gibt es diese auch nicht und damit können auch keine Weather dazu angelegt werden. In postgre musst Du letzendlich für komplizierte verschachtelungen Transactions benutzen sonst kannste auch gleich mysql nehmen, mit dem schon vorgeschlagenem Deferred und foreign Key solltest Du das dann hinbekommen. Da gibts schon einige Lösungen auf Deine Frage bei Stackoverflow.. ich benutze nur mysql.
Gerd schrieb: > aber eine > Inode zwingend mindestens einen Dateinamen braucht ergibt sich das > Problem. Für unixoide Dateisysteme ist das nicht richtig. Der Inode existiert, solange er referenziert wird. Ein Prozess kann einen Inode referenzieren und dann dürfen alle Verzeichniseinträge gelöscht werden. Dafür hat der Inode einen Referenzzähler. Geht dieser auf Null, so wird der Inode gelöscht. Edit: Also Trigger auf den Referenzzähler.
:
Bearbeitet durch User
der, der auch mal zockt schrieb: > Dann definiere doch ein DefaultWeather in cities. Darauf noch ein > constraint und das DefaultWeather mandatory. Dann hättest du doch deinen > Wunsch oder nicht? Aber auf welches Wetter sollte sich das Defaultwetter beziehen? Ich denke das Problem ist, dass das Ausgangsszenario mit dem City/Weather Beispiel nicht vergleichbar ist. Denn während eine inode mehreren Dateien zugeordnet werden kann, macht es wenig Sinn dass ein Wetter mehreren Städten zugeordnet ist. Hier fehlt eine Eindeutigkeit. Philipp K. schrieb: > Ja moment mal aber Du bist doch der Auslöser einer City.. wenn Du nie > eine City schreibst dann gibt es diese auch nicht und damit können auch > keine Weather dazu angelegt werden. Mir geht es nicht so sehr um das anlegen, sondern um das versehentliche löschen von Städten, für die noch Wetterdaten existieren, wobei diese Wetterdaten eventuell noch von anderen Städten referenziert werden, und dann nicht gelöscht werden dürfen.
Konrad S. schrieb: > Für unixoide Dateisysteme ist das nicht richtig. Der Inode existiert, > solange er referenziert wird. Ein Prozess kann einen Inode referenzieren > und dann dürfen alle Verzeichniseinträge gelöscht werden. Dafür hat der > Inode einen Referenzzähler. Geht dieser auf Null, so wird der Inode > gelöscht. war mir nicht klar, allerdings kann ich damit leben. Dass eine inode noch von einem Prozess referenziert wird ist ok. Ich möchte in diesem Fall keine 1:1 Kopie der iNodes der Partition haben, sondern nur den Teil der aus einem bestimmten Verzeichnis referenziert wird. Fehlen diese im Verzeichnisse werden sie aus der Datenbank gelöscht.
Oder man macht das ganz anders und Googelt mal nach "Postgre" oder "SQL" Tree/Node/Hierarchy. Vielleicht wäre so etwas einfach komfortabler: http://www.postgresql.org/docs/9.1/static/ltree.html
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.