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.
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.
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.
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.