Zwei Fremdschlüssel in einer Tabelle mit selbem Elternschlüssel?

Rakloedder

Benutzer
Beiträge
6
Hi :)

Habe früher mit einer Entwicklungsumgebung namens Clarion gearbeitet, in der man ein sog. dictionary definieren konnte, in der sämtliche Beziehungen zwischen Tabellen und noch einiges mehr bestimmt wurden.

Unter anderem konnte man dort ein ALIAS für eine Tabelle definieren; dort war es quasi eine virtuelle Kopie einer anderen Tabelle mit eigenem Namen. Bei Relationen wurden die Original-Tabelle und die Alias-Tabelle wie unabhängige Tabellen behandelt. Trotzdem: Wenn man in der Original-Tabelle etwas änderte, betraf diese Änderung auch die Alias-Tabelle und umgekehrt - logisch. Damit war es möglich, eine mehrfache 1:m-Relation zwischen zwei Tabellen zu machen. Beispiel:

* Eltern-Tabelle mit Flughafen-Namen als Primärschlüssel
* Kind-Tabelle mit Flugstrecken, bestehend aus Abflug-Flughafen und Ankunft-Flughafen jeweils als Fremdschlüssel.

Es soll eine zweifache 1:m-Relation zwischen den Tabellen bestehen, so dass bei einer Änderung des Flughafen-Namens in der Eltern-Tabelle die Namen auch in der Kind-Tabelle geändert werden, und zwar ggf. für Abflug- und Ankunft-Flughafen.

Geht das mit mySQL irgendwie?

Es ist mir klar, dass man das zum Beispiel mit Triggern erledigen könnte, aber wenn man anfängt, solche Grundaufgaben wie UPDATE oder DELETE mit Triggern zu erledigen, dann könnte man sich die automatische Referentielle Integrität von InnoDB auch gleich sparen...

Grüße
Ralph
 
Werbung:
Welche Referentielle Integrität von InnoDB meinst du? Meines wissens nach gibt es die nicht da Foreign Key Constraints in MySQL nicht durchgesetzt werden.

Du suchst ON UPDATE CASCADE auf deinen Foreign Key Constraints. Damit würde es gehen, ob MySQL das kann weiß ich nicht, ich zweifle daran.

Alternativ würde ich nicht Flughafen-Namen als PK wählen sondern immer einen künstlichen Schlüssel. Es erleichtert die Sache und man hat nur eine ID mehr die aber für jeden Anwender immer im Hintergrund bleibt.
 
Welche Referentielle Integrität von InnoDB meinst du? Meines wissens nach gibt es die nicht da Foreign Key Constraints in MySQL nicht durchgesetzt werden.

Doch, mit der InnoDB engine geht das.

Du suchst ON UPDATE CASCADE auf deinen Foreign Key Constraints. Damit würde es gehen, ob MySQL das kann weiß ich nicht, ich zweifle daran.

Alternativ würde ich nicht Flughafen-Namen als PK wählen sondern immer einen künstlichen Schlüssel. Es erleichtert die Sache und man hat nur eine ID mehr die aber für jeden Anwender immer im Hintergrund bleibt.

InnoDB kennt constraints der beschriebenen Art und setzt sie um

Ändert aber am Problem nix. Man kann ohne eine virtuelle Kopie der Eltern-Tabelle nicht eine Eltern-Tabelle zwei mal mit einer Kind-Tabelle verknüpfen.

Die Frage war ja, ob es in MySQL so etwas wie eine virtuelle Kopie gibt.
 
Also das von dir beschriebene Konstrukt mit einer art Schatten-Tabelle kenne ich so nicht, ich könnte es aber bauen aus Tabellen / Sichten. Das ist aber gar nicht nötig in diesem Fall.

Man kann ohne eine virtuelle Kopie der Eltern-Tabelle nicht eine Eltern-Tabelle zwei mal mit einer Kind-Tabelle verknüpfen.
Das ist nicht korrekt denn das mag unter MySQL nicht gehen, normalerweise ist das kein Problem. Hier mal ein Test mit MSSQL:
Code:
CREATE TABLE test_primaer(
   pk UNIQUEIDENTIFIER NOT NULL
   );

CREATE TABLE test_sekundaer(
   pk UNIQUEIDENTIFIER NOT NULL,
   fk1 UNIQUEIDENTIFIER NULL,
   fk2 UNIQUEIDENTIFIER NULL
   );

ALTER TABLE test_primaer ADD CONSTRAINT test_primaer_pk PRIMARY KEY(pk);
ALTER TABLE test_sekundaer ADD CONSTRAINT test_sekundaer_pk PRIMARY KEY(pk);
ALTER TABLE test_sekundaer ADD CONSTRAINT test_sekundaer_fk1 FOREIGN KEY(fk1) REFERENCES test_primaer(pk);
ALTER TABLE test_sekundaer ADD CONSTRAINT test_sekundaer_fk2 FOREIGN KEY(fk2) REFERENCES test_primaer(pk);

INSERT INTO test_primaer(pk) VALUES('CE5C3EAF-4B5B-4578-BCAE-60CFD15F552A');

SELECT * FROM test_primaer;
--CE5C3EAF-4B5B-4578-BCAE-60CFD15F552A

INSERT INTO test_sekundaer(pk,fk1,fk2) VALUES(newid(),'CE5C3EAF-4B5B-4578-BCAE-60CFD15F552A','CE5C3EAF-4B5B-4578-BCAE-60CFD15F552A');

SELECT * FROM test_sekundaer;
--A3C02DF6-0517-4513-9694-E92F9C3C526B   CE5C3EAF-4B5B-4578-BCAE-60CFD15F552A   CE5C3EAF-4B5B-4578-BCAE-60CFD15F552A

DELETE FROM test_primaer;
--Die DELETE-Anweisung steht in Konflikt mit der REFERENCE-Einschränkung 'test_sekundaer_fk1'. Der Konflikt trat in der xxx-Datenbank, Tabelle 'dbo.test_sekundaer', column 'fk1' auf.

UPDATE test_primaer SET pk = newid();
--Die UPDATE-Anweisung steht in Konflikt mit der REFERENCE-Einschränkung 'test_sekundaer_fk1'. Der Konflikt trat in der combit-Datenbank, Tabelle 'dbo.test_sekundaer', column 'fk1' auf.
Es werden definitiv zwei Fremdschlüssel von der sekundaer-Tabelle auf die primaer-Tabelle gesetzt. Der Test zeigt auch, das die Referentielle Integrität funktioniert. Ich bin mir sicher das MySQL auch mit InnoDB in der Vergangenheit zwar den Schlüssel erstellt hat, ihn dann aber beim gezeigten DELETE selbst verletzt und den DELETE ausgeführt hat.

Hier noch das, was du suchst:
Code:
ALTER TABLE test_sekundaer DROP CONSTRAINT test_sekundaer_fk1;
ALTER TABLE test_sekundaer DROP CONSTRAINT test_sekundaer_fk2;
ALTER TABLE test_sekundaer ADD CONSTRAINT test_sekundaer_fk1 FOREIGN KEY(fk1) REFERENCES test_primaer(pk) ON UPDATE CASCADE;

UPDATE test_primaer SET pk = newid();
--UPDATE test_primaer SET pk = newid();

SELECT * FROM test_primaer;
--AB3F6C3F-A968-49E9-AC5D-11EE68BC7272
SELECT * FROM test_sekundaer;
--A3C02DF6-0517-4513-9694-E92F9C3C526B    AB3F6C3F-A968-49E9-AC5D-11EE68BC7272    CE5C3EAF-4B5B-4578-BCAE-60CFD15F552A
CASCADE funktioniert, allerdings nicht mit zwei Fremdschlüsseln, zumindest hab ich es auf die Schnelle nicht hinbekommen. Ich finde CASCADE aber problematisch, ich würde wirklich einen rein künstlichen PK führen, das ist meiner Meinung nach deutlich eleganter als einen PK auf einen Namen wie in deinem Beispiel. Wäre der Name kein PK ließe er sich einfach ändern und würde immer richtig gejoint werden.
 
Hmmm. Also ich hab's jetzt mal mit dem Designer in phpMyAdmin versucht. Mag das Ding nicht, aber es hat tatsächlich dort funktioniert, was per SQL zu Fehlermeldungen geführt hat... Teste noch, ob das alles so funzt.
 
Gut, klappt es auch mit zwei Foreign Keys auf die Eltern-Tabelle aus der Kind-Tabelle? Wie gesagt unter MSSQL geht es, unter MySQL weiß ich nicht.
 
Alles einwandfrei. Alle constraints werden durchgesetzt, keine Probleme.

Sicher?

Probier mal aus, was da da in MySQL passiert:

Code:
test=*# create table rakloedder(i int check(i < 10));
CREATE TABLE
test=*# insert into rakloedder values (12);
ERROR:  new row for relation "rakloedder" violates check constraint "rakloedder_i_check"
DETAIL:  Failing row contains (12).
test=*#

Immer noch "alles einwandfrei"?
 
Werbung:
Zurück
Oben